I am sorting a dictionary, consisting of values & keys , by value. I have a hash of words and number of time used, that I want to order by number of time used.
There is a SortedList which is good for a single value , that I want to map it back to the word.
SortedDictionary orders by key, not value.
I could use a custom class, is there a better way.
I did some google searches but I can't find exactly what I am lookign for.
I found the answer
List<KeyValuePair<string, string>> BillsList = aDictionary.ToList();
BillsList.Sort(delegate(KeyValuePair<string, string> firstPair,
KeyValuePair<string, string> nextPair)
{
return firstPair.Value.CompareTo(nextPair.Value);
}
);
This should do it:
Dictionary<string, string> d = new Dictionary<string, string>
{
{"A","Z"},
{"B","Y"},
{"C","X"}
};
d.OrderBy(x=>x.Value).Select(x=>x.Key);
Will return C, B, A.
Here is using Linq and mapping the Count to the Word:
IDictionary<string, int> wordsAndCount = new Dictionary<string, int>
{
{"Batman", 987987987},
{"MeaningOfLife",42},
{"Fun",69},
{"Relaxing",420},
{"This", 2}
};
var result = wordsAndCount.OrderBy(d => d.Value).Select(d => new
{
Word = d.Key,
Count = d.Value
});
Result:
Related
i want to translate this line of code from php to asp.net
$subid[$value['parentid']][] = $value['id'];
i'm not familiar with asp.net data structure, i've tried arraylist but can't insert at [1], dictionary do not allow duplicated keys, anyone have ideas?
thanks
I'm not familiar with PHP (anymore) and SO is not a translation service, but you can use
List<Tuple<int, int>>
or
Lookup<int, int>
instead (assuming that your ids are ints).
var list = new List<Tuple<int, int>>();
list.Add(Tuple.Create(1, 1));
list.Add(Tuple.Create(1, 2));
list.Add(Tuple.Create(2, 3));
list.Add(Tuple.Create(2, 4));
list.Add(Tuple.Create(3, 5));
With Enumerable.ToLookup you can create a Lookup.
var lookup = list.ToLookup(t => t.Item1, t => t.Item2);
Find all products with parent-id = 1:
var parentID1 = lookup[1];
foreach (var value in parentID1)
Console.Write(value);
You can use a Dictionary with a little tweak to achieve what you want.
You create a dicionary like this:
Dictionary<string, List<string>> myDictionary = new Dictionary<string, List<string>>();
You add items to it like:
if(myDictionary.ContainsKey("myKey")) myDictionary["myKey"].Add("myItem");
else
{
myDictionary.Add("myKey", new List<string>(){"myItem"});
}
If you ask for a certain key, it will return a reference to the list with all related items.
How can i select the value from the List of keyvaluepair based on checking the key value
List<KeyValuePair<int, List<Properties>> myList = new List<KeyValuePair<int, List<Properties>>();
Here I want to get the
list myList[2].Value when myLisy[2].Key=5.
How can i achieve this?
If you need to use the List anyway I'd use LINQ for this query:
var matches = from val in myList where val.Key == 5 select val.Value;
foreach (var match in matches)
{
foreach (Property prop in match)
{
// do stuff
}
}
You may want to check the match for null.
If you're stuck with the List, you can use
myList.First(kvp => kvp.Key == 5).Value
Or if you want to use a dictionary (which might suit your needs better than the list as stated in the other answers) you can convert your list to a dictionary easily:
var dictionary = myList.ToDictionary(kvp => kvp.Key);
var value = dictionary[5].Value;
Use Dictionary<int, List<Properties>>. Then you can do
List<Properties> list = dict[5];
As in:
Dictionary<int, List<Properties>> dict = new Dictionary<int, List<Properties>>();
dict[0] = ...;
dict[1] = ...;
dict[5] = ...;
List<Properties> item5 = dict[5]; // This works if dict contains a key 5.
List<Properties> item6 = null;
// You might want to check whether the key is actually in the dictionary. Otherwise
// you might get an exception
if (dict.ContainsKey(6))
item6 = dict[6];
NOTE
The generic Dictionary class, introduced in .NET 2.0, uses KeyValuePair.
ITs better you make use of
Dictionary<TKey, TValue>.ICollection<KeyValuePair<TKey, TValue>>
and use ContainsKey Method to check the the key is there or not ..
Example :
ICollection<KeyValuePair<String, String>> openWith =
new Dictionary<String, String>();
openWith.Add(new KeyValuePair<String,String>("txt", "notepad.exe"));
openWith.Add(new KeyValuePair<String,String>("bmp", "paint.exe"));
openWith.Add(new KeyValuePair<String,String>("dib", "paint.exe"));
openWith.Add(new KeyValuePair<String,String>("rtf", "wordpad.exe"));
if (!openWith.ContainsKey("txt"))
{
Console.WriteLine("Contains Given key");
}
EDIT
To get value
string value = "";
if (openWith.TryGetValue("tif", out value))
{
Console.WriteLine("For key = \"tif\", value = {0}.", value);
//in you case
//var list= dict.Values.ToList<Property>();
}
in your caseu it will be
var list= dict.Values.ToList<Property>();
I was wondering if it were possible to make a list from the dictionary values where the key is a specified value?
The dictionary would like this:
Sidcup - DPC1
Sidcup - DPC2
Blackheath - DPC3
Blackheath - DPC4
Bexleyheath - DPC5
In fact, I'm not entirely implementing a Dictionary as above is a good idea. Here is its implementation:
DataSet ds = EngineBllUtility.GetDPCsForImportFile(connectionString, fileID);
if (ds.Tables.Count > 0)
{
DataTable dtDPCs = EngineBllUtility.GetDPCsForImportFile(connectionString, fileID).Tables[0];
Dictionary<string, string> preliminaryList = new Dictionary<string, string>();
if (dtDPCs.Columns.Contains("DPCNumber") && dtDPCs.Columns.Contains("BranchName"))
foreach (DataRow dataRow in dtDPCs.Rows)
{
preliminaryList.Add(dataRow["BranchName"].ToString(), dataRow["DPCNumber"].ToString());
}
I have the following code: (Excuse the last line, its just so you have an idea of what I'm trying to do).
foreach (string branch in branchNames)
{
string subfolder = System.IO.Path.Combine(saveLocation, branch);
System.IO.Directory.CreateDirectory(subfolder);
List<string> certificateList = new List<string>();
certificateList.Add(DPCNumber in preliminaryList where Key = branch);
}
In the above the branch is the key from the Dictionary. I need to iterate through because it needs to create a new folder and then do something with the certificateList I am creating.
Sure:
private static void TestZip()
{
Dictionary<string, string> stringstringdic = new Dictionary<string, string>();
stringstringdic.Add("1", "One");
stringstringdic.Add("2", "Two");
stringstringdic.Add("3", "Three");
stringstringdic.Add("4", "Four");
stringstringdic = stringstringdic.Where(pair => pair.Key != "1")
.ToDictionary(pair => pair.Key, pair => pair.Value);
List<string> stringlist = stringstringdic.Keys.Concat(stringstringdic.Values).ToList();
foreach (string str in stringlist)
{
Console.WriteLine(str);
}
}
//Output:
//2
//3
//4
//Two
//Three
//Four
Of course, you'll have to change the Where clause to reflect your real need.
If I understood you right, it's like .Where(pair => pair.Key == branch)
If I understand you correctly you want to add the value based on a key to a separate List?
certificateList.Add(preliminaryList[branch])
This is simplified as I really need to see the declaration of preliminaryList to know how DPCNumber fits into all of it. Could it be...
certificateList.Add(preliminaryList[branch].ToString())
To simply create a list of keys you can do the following.
var dictionary = new Dictionary<string, string>();
dictionary.Add("key1", "value1");
dictionary.Add("key2", "value2");
dictionary.Add("key3", "value3");
dictionary.Add("key4", "value4");
dictionary.Add("key5", "value5");
var list = dictionary.Keys.ToList();
This should give you a list with values "key1", "key2", "key3", "key4", "key5".
You can put a where clause in to filter out certain keys. The following gives all keys which contain a "2" (random example), resulting in just "key2".
var filteredList = dictionary.Keys.Where(key => key.Contains("2")).ToList();
Edit:
To get a value given a specific key.
string value = dictionary["key1"];
Note, the key is a dictionary must be unique, so for a given key you will only ever get a single value back and not a list of values.
What is the 'best' way to sort (or iterate) over a StringDictionary in order of Value (not Key)
E.g. Key - Value
1 - X label
2 - A label
3 - Other label
would give
2 - A label
3 - Other label
1 - X label
EDIT - I meant to say "using .NET 2.0 features". Sorry, me bad...
Use LINQ:
var items = from k in d.Keys
orderby d[k] ascending
select k;
If you are restricted to C# 2.0 features, use this:
IDictionary<string, string> d = new Dictionary<string, string>();
d["1"] = "X label";
d["2"] = "A label";
d["3"] = "Other Label";
List<KeyValuePair<string, string>> myList = new List<KeyValuePair<string, string>>(d);
myList.Sort(
delegate(KeyValuePair<string, string> a,
KeyValuePair<string, string> b)
{
return a.Value.CompareTo(b.Value);
}
);
Note:
If you are using a StringDictionary instead of Dictionary, check out Anthony's solution.
Using the StringDictionary class, here is a method to use LINQ's OrderBy. Assumes you have .NET 3.5.
var sortedDictionary = dictionary.Cast<DictionaryEntry>().OrderBy(pair => pair.Value);
Using 2.0, it's a bit trickier. Here's an approach using a Comparison delegate.
StringDictionary dictionary = new StringDictionary();
dictionary.Add("1", "One");
dictionary.Add("2", "Two");
dictionary.Add("3", "Three");
DictionaryEntry[] sortedDictionary = new DictionaryEntry[dictionary.Count];
dictionary.CopyTo(sortedDictionary, 0);
Comparison<DictionaryEntry> comparison = new Comparison<DictionaryEntry>(delegate (DictionaryEntry obj1, DictionaryEntry obj2) { return ((string)obj1.Value).CompareTo((string)obj2.Value); });
Array.Sort(sortedDictionary, comparison);
So the actual sort would be in the sortedDictionary array.
i have a generic sorted list "results" with key = some filename and value = boolean.
I would like to sort the list by the boolean entry or value column. does anyone know how i can do this?
Thanks!
SortedList is optimized so that inertions occur in an ordered fashion, such that enumeration occurs in a sorted order at minimal cost. Anything else requires a re-sort. Thus:
SortedList<string,bool> l = new SortedList<string, bool>();
l.Add("a", true);
l.Add("b", false);
l.Add("c", true);
l.Add("d", false);
var orderByVal = l.OrderBy(kvp => kvp.Value);
but this enumeration will be significantly slower to calculate, and be performed up-front, requiring extra storage to do so.
Depending on your situation it might be cheaper to maintain 2 SortedList instances with the key/value reversed.
In .NET 2.0, you could add your items to a SortedList:
public static List<MyObject> SortedObjects(IEnumerable<MyObject> myList) {
SortedList<string, MyObject> sortedList = new SortedList<string, MyObject>();
foreach (MyObject object in myList) {
sortedList.Add(object.ValueIWantToSort, object);
}
return new List<MyObject>(sortedList.Values);
}
For descending all list items
list.OrderByDescending();
or
var list = list.OrderByDescending(x => x.Product.Name)
.ThenBy(x => x.Product.Price).ToList();
Normally that sorted by the first key on the list so if you swap the key and value on the add, then match that on the binding
that sample example i use and work fine
public static SortedList<string, string> GetCountries(string conn)
{
var dict = new SortedList<string, string>();
dict.Add("","Select One");
var sql = "SELECT [CountryID] ,[Descr] FROM [dbo].[Countries] Order By CountryID ";
using (var rd = GetDataReader(conn, sql))
{
while (rd.Read())
{
dict.Add(rd["Descr"].ToString(), rd["CountryID"].ToString());
}
}
return dict;
}
Dim List As SortedList(Of String, String) = VDB.CoreLib.DbUtils.GetCountries(connDB)
ddlBankCountry.DataSource = List
ddlBankCountry.DataTextField = "Key"
ddlBankCountry.DataValueField = "Value"
ddlBankCountry.DataBind()