c# sorting a StringDictionary by value, NOT key - c#

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.

Related

C# How can I print all elements from List<Dictionary<string,string>> on the console?

I’m a rookie in programming and I have a problem understanding how to print elements from a List.
In the task I’ve been given, I receive:
List<Dictionary<string,string>>() list = new
List<Dictionary<string,string>>();
list.Add(processString(string, string));
list.Add(processString(string, string));
The processStrig is a Dictionary<string,string> and the keys are the same for both records.
I tried to create a new Dictionary and then populate it with foreach:
Dictionary<string,string>() dict = new Dictionary<string, string>();
foreach (Dictionary<string,string>r in list)
{
foreach (string inner in r.Keys)
{
if (!dict.ContainsKey(inner))
{
dict.Add(inner, r[inner]);
}
}
}
and then print the new dict with another foreach, but it shows me only the first input because the keys are the same. So basically my question is how to print the both inputs? The output should look like this:
The output should look like this:
[0]
"count":"some string"
"order":"some string"
[1]
"count":"some other string"
"order":"some other string"
If you are looking for a loop solution, you can try something like this:
List<Dictionary<string, string>> list = ...
for (int i = 0; i < list.Count; ++i) {
Console.WriteLine($"[{i}]");
if (list[i] == null)
Console.WriteLine("[null]");
else
foreach (var pair in list[i])
Console.WriteLine($"\"{pair.Key}\" : \"{pair.Value}\"");
}
Let's have a method that makes you a dictionary:
public static Dictionary<string, string> MakeMeADictionary(string value1, string value2){
var d = new Dictionary<string, string>();
d["key1"] = value1;
d["key2"] = value2;
return d;
}
Let's call it twice, adding the results to a List:
var listOfDicts = new List<Dictionary<string, string>>();
listOfDicts.Add(MakeMeADictionary("first val", "second val"));
listOfDicts.Add(MakeMeADictionary("third val", "fourth val"));
Let's enumerate the list, and then each dictionary inside it:
foreach(var dict in listOfDicts){
Console.WriteLine("Enumerating a dictionary");
foreach(var keyValuePair in dict)
Console.WriteLine($"Key is: {keyValuePair.Key}, Value is: {keyValuePair.Value}");
}
Result:
Enumerating a dictionary
Key is: key1, Value is: first val
Key is: key2, Value is: second val
Enumerating a dictionary
Key is: key1, Value is: third val
Key is: key2, Value is: fourth val
Strive for variable names that make your code make sense; plurals or names of colelction types for collections, foreach vars that singularly make sense for the plural being enumerated etc.. If this were a less contrived example, and e.g. it were a List<Person> I'd call it people, perhaps, and have foreach(var person in people).. I couldn't understand your choice of r in foreach(var r in list)

C# sort a dictionary by value

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:

2-dimensional array with duplicated index key

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.

Select Value of List of KeyValuePair

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>();

c# How to sort a sorted list by its value column

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()

Categories