I have a dictionary of city-population objects:
var cityPopulation = new new Dictionary<string, int>()
{
["Sacramento"] = 495234,
["Miami"] = 453579,
["Memphis"] = 652717
});
I need to get 2 corresponding (same order) arrays. Can I be sure that when I do
var cities = cityPopulation.Keys.ToArray();
var populations = cityPopulation.Values.ToArray();
Order of both arrays will be preserved - i.e.:
cities - 1st element will be Sacramento, 2nd - Miami and 3rd - Memphis, and for array of populations - 1st - 495234, 2nd - 453579 and 3rd - 652717 correspondingly (array of cities should correspond to the array of populations).
How can I be sure about this, and if not - how do I preserve the order of those arrays?
No. Dictionary<TKey, TValue> does not preserve ordering.
For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair<TKey, TValue> structure representing a value and its key. The order in which the items are returned is undefined.
From Dictionary<TKey, TValue> Class on MSDN
For Keys and Value properties documentation says their order is not specified, but it's consistent between the two:
The order of the values in the Dictionary<TKey, TValue>.ValueCollection is unspecified, but it is the same order as the associated keys in the Dictionary<TKey, TValue>.KeyCollection returned by the Keys property.
From Dictionary<TKey, TValue>.Values Property on MSDN
No, they don't "preserve order." Or, to be more precise, they do preserve order, but a dictionary isn't ordered to begin with.
That being said, it looks like your actual requirement is to produce two arrays that contain the items found in the dictionary and also correlate with one another. Such an arrangement is known as parallel arrays.
To make this happen, you just need to create an enumeration that is sorted deterministically (doesn't matter by what, but the key is a pretty obvious candidate, since it is guaranteed to be unique). Once you have a sorted list, just select the keys and values into their own arrays.
var sortedPopulation = cityPopulation.OrderBy( a => a.Key );
string[] cities = sortedPopulation.Select( a => a.Key ).ToArray();
int[] populations = sortedPopulation.Select( a => a.Value ).ToArray();
This should give you the two arrays you need, with elements aligned, even if they are not in the "original sort order" (which technically doesn't even exist).
Full example:
public static void Main()
{
var cityPopulation = new Dictionary<string, int>
{
{"Sacramento",495234 },
{"Miami", 453579 },
{"Memphis", 652717 }
};
var sortedPopulation = cityPopulation.OrderBy( a => a.Key );
string[] cities = sortedPopulation.Select( a => a.Key ).ToArray();
int[] populations = sortedPopulation.Select( a => a.Value ).ToArray();
foreach (var c in cities)
Console.WriteLine(c);
foreach (var p in populations)
Console.WriteLine(p);
}
Output:
Memphis
Miami
Sacramento
652717
453579
495234
If for some reason you would like to get the results without sorting and without enumerating the original list twice, you could also do something like this:
public static void SplitDictionary<T1, T2>(Dictionary<T1, T2> input, out T1[] keys, out T2[] values)
{
keys = new T1[input.Count];
values = new T2[input.Count];
int i = 0;
foreach ( var entry in input )
{
keys[i] = entry.Key;
values[i++] = entry.Value;
}
}
This works because, even though the dictionary can't be relied on for its order, we retrieve the key and value at the same time. Once they are retrieved and put into an array, their order is fixed.
See my code on DotNetFiddle
A dictionary is non-deterministic. There is no implicit ordering of hashtables. In short do not rely on the order being the same as when you added the values.
For purposes of enumeration, each item in the dictionary is treated as
a KeyValuePair structure representing a value and its
key. The order in which the items are returned is undefined.
You can read more here
public static Hashtable Drinks = new Hashtable();
Drinks["Water"] = 3;
Drinks["Coffee"] = 2
Drinks["Beer"] = 5;
To get the value of item I use:
int drink = (int)Drinks["Water"];
which works.
I wanted to know how i can make this work.
pCardValue1 = (int)card[1];
Like instead of typing the item name i want to get the value by position.
The Hashtable (and Dictionary) class is not ordered, meaning, it's entries don't have any order or position, and even if you get a list of keys, the order is random. If you want to get values by key and position as well, you should use the OrderedDictionary collection.
You need a OrderedDictionary. HashTable is not ordered.
Also note that HashTable should not be used in production code from framework 2.0, there is a Dictionary<TKey,TValue> class in System.Collections.Generic namespace which is a replacement for HashTable and provides generics.
As already mentioned, you should use OrderedDictionary. Since you asked for an example in the comments, here is one:
var stringKey = "stringKey";
var stringValue = "stringValue";
var objectKey = "dateTimeKey";
var objectValue = DateTime.Now;
var dict = new OrderedDictionary();
dict.Add(stringKey, stringValue);
dict.Add(objectKey, objectValue);
for (int i = 0; i < dict.Count; i++)
{
var value = dict[i];
}
Enumerating the dictionary several times will return the results in the same order. Note that since it accepts an Object for both key and value, you can mix different types as much as you want, meaning you have to be careful when you use the structure.
you can use linq trick to get item name at position.
int position = 1;
var a1 = (from DictionaryEntry entry in Drinks select entry.Key).Skip(position).FirstOrDefault();
If you want item name by value then use
object value = 2;
var a = (from DictionaryEntry entry in Drinks where entry.Value.Equals(value) select entry.Key).FirstOrDefault();
I'm not very familiar with Java, and I'm a bit unsure of how to translate this from c# into java.
Dictionary<string, int> myDictionary = GetDictionary();
int N = 10;
myDictionary
.OrderByDescending(dictionaryEntry => dictionaryEntry.Value)
.Take(N)
.Select(dictionaryEntry => dictionaryEntry.Key)
.ToList();
Now, I KNOW the dictionary itself isnt being sorted, its just a new IEnumberable, and that's OK.
Thanks!
I'm not a C# guy, I've never worked with it, but if I should take a guess it seems like you are sorting the map by its values in descending order, retrieving the 10 first elements, then converting the keys of those 10 elements into a list.
If the values are known to be distinct, then it's kind of trivial - you just convert to a SortedMap with keys and values exchanged. So I'm assuming that the values are not distinct, i.e. that the same number may appear multiple times.
In that case it's not as trivial, and definitely not as simple as in your C# example. My first thought was to create a sorted set with a custom comparator, where each element in the set is a Map.Entry from your map, where the keys and values are exchanged.
This will actually require quite a bit of code in Java. Heres one attempt:
// Create a SortedSet of the reversed entry set, with a custom comparator for sorting
SortedSet<Map.Entry<Integer, String>> sortedSet = new TreeSet<Map.Entry<Integer, String>>(
new Comparator<Map.Entry<Integer, String>>() {
public int compare(Map.Entry<Integer, String> o1, Map.Entry<Integer, String> o2) {
// sort by key, then by value --> in descending order
int keyCompareResult = -o1.getKey().compareTo(o2.getKey()); // negate --> descending
int valueCompareResult = o1.getValue().compareTo(o2.getValue());
return keyCompareResult == 0 ? valueCompareResult : -keyCompareResult;
}
});
// Add all entries of the map to the sorted set
for (Map.Entry<String, Integer> entry : map.entrySet()) {
Map.Entry<Integer, String> reversedEntry = new AbstractMap.SimpleEntry<Integer, String>(entry.getValue(), entry.getKey());
sortedSet.add(reversedEntry);
}
// Convert the 10 first elements to the resulting list
int N = 10;
List<String> result = new ArrayList<String>(N);
Iterator<Map.Entry<Integer,String>> iterator = sortedSet.iterator();
while (iterator.hasNext() && result.size() < N) {
Map.Entry<Integer, String> entry = iterator.next();
result.add(entry.getValue());
}
I came up with pretty much the same thing as Steinar suggested, if you know of a more LINQ-y/functional way to do it, please add your answer too!
//Convert to List of Map.Entry
ArrayList<Map.Entry<String,Integer>> myArrayList = ArrayList<Map.Entry<String,Integer>>(myHashMap.entrySet());
//Natural order is ascending, so we reverse the comparator to get it Descending.
Collections.sort(myArrayList , Collections.reverseOrder(new EntryComparator()));
//Create list and add Keys
List<String> topNStrings = new ArrayList<String>();
for (int i = 0; i < N && i < myArrayList.size(); i++)
{
topNStrings.add(myArrayList.get(i).getKey());
}
and had a separate little comparator class
private class EntryComparator implements Comparator<Map.Entry<String,Integer>>
{
#Override
public int compare(Map.Entry<String,Integer> x, Map.Entry<String,Integer> y)
{
return compare(x.getValue(), y.getValue());
}
private int compare(Integer a, Integer b)
{
return a < b ? -1
: a > b ? 1
: 0;
}
}
Let us start with an arbitrary HashMap that you have acquired somehow defined by HashMap<String, Integer> map.
We want to sort the values and then get the first N values.
int N = 10;
List<Integer> values = new ArrayList<Integer>( map.values() );
Collections.sort(values);
List<Integer> N_values = values.subList(0, N);
For each item in the collection, I need to have a short string and a few int16 fields. I want to iterate through the collection using the string field (meaning I don't want to use numeric index to iterate).
The collection is at most about 10 items. Thanks for any suggestions.
I think Dictionary<string, List<int>> should work for you needs.
Dictionary<string, List<int>> dictionary = new Dictionary<string, List<int>>();
dictionary.Add("key", new List<int>{1,2,3,4});
...
If you use .NET 4 and the "few int16" are always the same number of values you might also want to consider the Tuple class as value in the dictionary:
var map = new Dictionary<string, Tuple<Int16, Int16, Int16>>();
map["Foo"] = Tuple.Create(1, 2, 3);
var values = map["Foo"];
Console.WriteLine("{0} {1} {2}", value.Item1, value.Item2, value.Item3);
I would use a Dictionary so you can index into it using an arbitrary key - string, in your case.
If you mean iterate as looping thru; then it really does not matter because all collections support foreach:
foreach (var item in collection) { ... }
However, if you mean iterate as indexing, then a Dictionary should do the job.
class SomeFields { public int a; public int b; ... }
var collection = new Dictionary<string, SomeFields>();
collection.Add("name", new SomeFields() { a = 1, b = 2 });
var fields = collection["name"];
If the items in the collection is small "10 items or less" then better for performance to use ListDictionary, If you are not sure about the elements count or if the element count maybe increase in the future then use HaybridDictionary.
Note that HybridDictionary mechanism is to use internally a ListDictionary while the collection is small, and then switching to a Hashtable when the collection gets large.
I often have to sort a dictionary (consisting of keys & values) by value. For example, I have a hash of words and respective frequencies that I want to order by frequency.
There is a SortedList which is good for a single value (say frequency), that I want to map back to the word.
SortedDictionary orders by key, not value. Some resort to a custom class, but is there a cleaner way?
Use LINQ:
Dictionary<string, int> myDict = new Dictionary<string, int>();
myDict.Add("one", 1);
myDict.Add("four", 4);
myDict.Add("two", 2);
myDict.Add("three", 3);
var sortedDict = from entry in myDict orderby entry.Value ascending select entry;
This would also allow for great flexibility in that you can select the top 10, 20 10%, etc. Or if you are using your word frequency index for type-ahead, you could also include StartsWith clause as well.
Use:
using System.Linq.Enumerable;
...
List<KeyValuePair<string, string>> myList = aDictionary.ToList();
myList.Sort(
delegate(KeyValuePair<string, string> pair1,
KeyValuePair<string, string> pair2)
{
return pair1.Value.CompareTo(pair2.Value);
}
);
Since you're targeting .NET 2.0 or above, you can simplify this into lambda syntax -- it's equivalent, but shorter. If you're targeting .NET 2.0 you can only use this syntax if you're using the compiler from Visual Studio 2008 (or above).
var myList = aDictionary.ToList();
myList.Sort((pair1,pair2) => pair1.Value.CompareTo(pair2.Value));
You could use:
var ordered = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
You can sort a Dictionary by value and save it back to itself (so that when you foreach over it the values come out in order):
dict = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
Sure, it may not be correct, but it works. Hyrum's Law means that this will very likely continue to work.
Looking around, and using some C# 3.0 features we can do this:
foreach (KeyValuePair<string,int> item in keywordCounts.OrderBy(key=> key.Value))
{
// do something with item.Key and item.Value
}
This is the cleanest way I've seen and is similar to the Ruby way of handling hashes.
On a high level, you have no other choice than to walk through the whole Dictionary and look at each value.
Maybe this helps:
http://bytes.com/forum/thread563638.html
Copy/Pasting from John Timney:
Dictionary<string, string> s = new Dictionary<string, string>();
s.Add("1", "a Item");
s.Add("2", "c Item");
s.Add("3", "b Item");
List<KeyValuePair<string, string>> myList = new List<KeyValuePair<string, string>>(s);
myList.Sort(
delegate(KeyValuePair<string, string> firstPair,
KeyValuePair<string, string> nextPair)
{
return firstPair.Value.CompareTo(nextPair.Value);
}
);
You'd never be able to sort a dictionary anyway. They are not actually ordered. The guarantees for a dictionary are that the key and value collections are iterable, and values can be retrieved by index or key, but there is no guarantee of any particular order. Hence you would need to get the name value pair into a list.
You do not sort entries in the Dictionary. Dictionary class in .NET is implemented as a hashtable - this data structure is not sortable by definition.
If you need to be able to iterate over your collection (by key) - you need to use SortedDictionary, which is implemented as a Binary Search Tree.
In your case, however the source structure is irrelevant, because it is sorted by a different field. You would still need to sort it by frequency and put it in a new collection sorted by the relevant field (frequency). So in this collection the frequencies are keys and words are values. Since many words can have the same frequency (and you are going to use it as a key) you cannot use neither Dictionary nor SortedDictionary (they require unique keys). This leaves you with a SortedList.
I don't understand why you insist on maintaining a link to the original item in your main/first dictionary.
If the objects in your collection had a more complex structure (more fields) and you needed to be able to efficiently access/sort them using several different fields as keys - You would probably need a custom data structure that would consist of the main storage that supports O(1) insertion and removal (LinkedList) and several indexing structures - Dictionaries/SortedDictionaries/SortedLists. These indexes would use one of the fields from your complex class as a key and a pointer/reference to the LinkedListNode in the LinkedList as a value.
You would need to coordinate insertions and removals to keep your indexes in sync with the main collection (LinkedList) and removals would be pretty expensive I'd think.
This is similar to how database indexes work - they are fantastic for lookups but they become a burden when you need to perform many insetions and deletions.
All of the above is only justified if you are going to do some look-up heavy processing. If you only need to output them once sorted by frequency then you could just produce a list of (anonymous) tuples:
var dict = new SortedDictionary<string, int>();
// ToDo: populate dict
var output = dict.OrderBy(e => e.Value).Select(e => new {frequency = e.Value, word = e.Key}).ToList();
foreach (var entry in output)
{
Console.WriteLine("frequency:{0}, word: {1}",entry.frequency,entry.word);
}
You could use:
Dictionary<string, string> dic= new Dictionary<string, string>();
var ordered = dic.OrderBy(x => x.Value);
return ordered.ToDictionary(t => t.Key, t => t.Value);
Or for fun you could use some LINQ extension goodness:
var dictionary = new Dictionary<string, int> { { "c", 3 }, { "a", 1 }, { "b", 2 } };
dictionary.OrderBy(x => x.Value)
.ForEach(x => Console.WriteLine("{0}={1}", x.Key,x.Value));
Sorting a SortedDictionary list to bind into a ListView control using VB.NET:
Dim MyDictionary As SortedDictionary(Of String, MyDictionaryEntry)
MyDictionaryListView.ItemsSource = MyDictionary.Values.OrderByDescending(Function(entry) entry.MyValue)
Public Class MyDictionaryEntry ' Need Property for GridViewColumn DisplayMemberBinding
Public Property MyString As String
Public Property MyValue As Integer
End Class
XAML:
<ListView Name="MyDictionaryListView">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Path=MyString}" Header="MyStringColumnName"></GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Path=MyValue}" Header="MyValueColumnName"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
The other answers are good, if all you want is to have a "temporary" list sorted by Value. However, if you want to have a dictionary sorted by Key that automatically synchronizes with another dictionary that is sorted by Value, you could use the Bijection<K1, K2> class.
Bijection<K1, K2> allows you to initialize the collection with two existing dictionaries, so if you want one of them to be unsorted, and you want the other one to be sorted, you could create your bijection with code like
var dict = new Bijection<Key, Value>(new Dictionary<Key,Value>(),
new SortedDictionary<Value,Key>());
You can use dict like any normal dictionary (it implements IDictionary<K, V>), and then call dict.Inverse to get the "inverse" dictionary which is sorted by Value.
Bijection<K1, K2> is part of Loyc.Collections.dll, but if you want, you could simply copy the source code into your own project.
Note: In case there are multiple keys with the same value, you can't use Bijection, but you could manually synchronize between an ordinary Dictionary<Key,Value> and a BMultiMap<Value,Key>.
Actually in C#, dictionaries don't have sort() methods.
As you are more interested in sort by values,
you can't get values until you provide them key.
In short, you need to iterate through them using LINQ's OrderBy(),
var items = new Dictionary<string, int>();
items.Add("cat", 0);
items.Add("dog", 20);
items.Add("bear", 100);
items.Add("lion", 50);
// Call OrderBy() method here on each item and provide them the IDs.
foreach (var item in items.OrderBy(k => k.Key))
{
Console.WriteLine(item);// items are in sorted order
}
You can do one trick:
var sortedDictByOrder = items.OrderBy(v => v.Value);
or:
var sortedKeys = from pair in dictName
orderby pair.Value ascending
select pair;
It also depends on what kind of values you are storing: single (like string, int) or multiple (like List, Array, user defined class).
If it's single you can make list of it and then apply sort.
If it's user defined class, then that class must implement IComparable, ClassName: IComparable<ClassName> and override compareTo(ClassName c) as they are more faster and more object oriented than LINQ.
Required namespace : using System.Linq;
Dictionary<string, int> counts = new Dictionary<string, int>();
counts.Add("one", 1);
counts.Add("four", 4);
counts.Add("two", 2);
counts.Add("three", 3);
Order by desc :
foreach (KeyValuePair<string, int> kvp in counts.OrderByDescending(key => key.Value))
{
// some processing logic for each item if you want.
}
Order by Asc :
foreach (KeyValuePair<string, int> kvp in counts.OrderBy(key => key.Value))
{
// some processing logic for each item if you want.
}
Suppose we have a dictionary as:
Dictionary<int, int> dict = new Dictionary<int, int>();
dict.Add(21,1041);
dict.Add(213, 1021);
dict.Add(45, 1081);
dict.Add(54, 1091);
dict.Add(3425, 1061);
dict.Add(768, 1011);
You can use temporary dictionary to store values as:
Dictionary<int, int> dctTemp = new Dictionary<int, int>();
foreach (KeyValuePair<int, int> pair in dict.OrderBy(key => key.Value))
{
dctTemp.Add(pair.Key, pair.Value);
}
The easiest way to get a sorted Dictionary is to use the built in SortedDictionary class:
//Sorts sections according to the key value stored on "sections" unsorted dictionary, which is passed as a constructor argument
System.Collections.Generic.SortedDictionary<int, string> sortedSections = null;
if (sections != null)
{
sortedSections = new SortedDictionary<int, string>(sections);
}
sortedSections will contain the sorted version of sections
Sort and print:
var items = from pair in players_Dic
orderby pair.Value descending
select pair;
// Display results.
foreach (KeyValuePair<string, int> pair in items)
{
Debug.Log(pair.Key + " - " + pair.Value);
}
Change descending to acending to change sort order
A dictionary by definition is an unordered associative structure that contains only values and keys in a hashable way. In other words has not a previsible way to orderer a dictionary.
For reference read this article from python language.
Link
python data structures
Best way:
var list = dict.Values.OrderByDescending(x => x).ToList();
var sortedData = dict.OrderBy(x => list.IndexOf(x.Value));
The following code snippet sorts a Dictionary by values.
The code first creates a dictionary and then uses OrderBy method to sort the items.
public void SortDictionary()
{
// Create a dictionary with string key and Int16 value pair
Dictionary<string, Int16> AuthorList = new Dictionary<string, Int16>();
AuthorList.Add("Mahesh Chand", 35);
AuthorList.Add("Mike Gold", 25);
AuthorList.Add("Praveen Kumar", 29);
AuthorList.Add("Raj Beniwal", 21);
AuthorList.Add("Dinesh Beniwal", 84);
// Sorted by Value
Console.WriteLine("Sorted by Value");
Console.WriteLine("=============");
foreach (KeyValuePair<string, Int16> author in AuthorList.OrderBy(key => key.Value))
{
Console.WriteLine("Key: {0}, Value: {1}", author.Key, author.Value);
}
}
You can sort the Dictionary by value and get the result in dictionary using the code below:
Dictionary <<string, string>> ShareUserNewCopy =
ShareUserCopy.OrderBy(x => x.Value).ToDictionary(pair => pair.Key,
pair => pair.Value);
Given you have a dictionary you can sort them directly on values using below one liner:
var x = (from c in dict orderby c.Value.Order ascending select c).ToDictionary(c => c.Key, c=>c.Value);