I have a dictionary which is sorted in descending order.Each string (key) is a term and the int (value) its count. How I get the first count? because it refers to the maximum count (frequency)....... thanks in advance.
Just to inform some of whom commented that the dictionary<string,int> will change its
rank. Be sure, if you are grouping the dictionary by its count, there is no problem
with the order . Always the dictionary will come with highest count at first.
What do you mean by 'dictionary sorted in descending order'? A Dictionary<TKey,TValue> by definition is unsorted! Do you mean SortedDictionary<TKey,TValue>? If so, you can use:
var firstCount = sortedDictionary.First().Value;
You cannot depend on a Dictionary to stay ordered (except it is an OrderedDictionary of course). If you are using an OrderedDictionary, you can use its indexer:
var maximumCount = myDictionary[0];
or
var maximumCount = myDictionary.First().Value;
EDIT: If you want the highest count in the entire dictionary, you could also just use this:
var maximumCount = myDictionary.Max(entry => entry.Value);
What about the below
yourDictionary.First().Value
bear in mind that as you add more values it may very well change order
MSDN warns about that
http://msdn.microsoft.com/en-us/library/ekcfxy3x(v=vs.100).aspx
I believe you're using the wrong type of Dictionary. Use an OrderedDictionary<> instead. It will provide you with a guaranteed order and an indexer.
OrderedDictionary list = new OrderedDictionary();
// add a bunch of items
int firstValue = (int)list[0];
The only drawback with an OrderedDictionary is that it's not generic, but here's how you can make it generic. http://www.codeproject.com/Articles/18615/OrderedDictionary-T-A-generic-implementation-of-IO
Related
I have a integer List List<int> iFaciltyReqId = new List<int>(); and its elements are
I need to order the hashtable below like the above List(need to exclude if the element not exist)
My hashtable is
Result should be hastable keys in the order
1153
1168
1155
1152
1176
676
I tried as below, but the result is not meeting my expectation
foreach (var c in iFaciltyReqId)
{
foreach (var d in ohmItemSeqs.Keys)
{
if (Convert.ToInt32(c) == Convert.ToInt32(d))
{
sortedohmItemSeqs.Add(c, ohmItemSeqs.Values);
}
}
}
and result was
Any help will be appreciated.
I would suggest you simply take your list and return everything that's also in the hash table like so:
var result = yourList.Where(i => yourHashTable.Contains(i)); // works for both HashSet<int> and Hashtable
A Hashtable is fundamentally an unordered data structure, so you'll want to look at alternatives if maintaining order is important.
If you want the order to be determined by insertion, OrderedDictionary may be a suitable option, although that depends on what your other needs for the object are.
I'm having a problem sorting a dictionary based on the sum of 1s in lists of integers inside the same Dictionary. So first I want to count the 1s in each list and then sort the dictionary based on the result.
I've found some solutions in Stackoverflow but they don't answer my question.
Th dictionary looks like the following:
Dictionary<int, List<int>> myDic = new Dictionary<int, List<int>>();
List<int> myList = new List<int>();
myList = new List<int>();//Should appear third
myList.Add(0);
myList.Add(0);
myList.Add(1);
myDic.Add(0, myList);
myList = new List<int>();//Should appear second
myList.Add(1);
myList.Add(1);
myList.Add(0);
myDic.Add(1, myList);
myList = new List<int>();//Should appear first
myList.Add(1);
myList.Add(1);
myList.Add(1);
myDic.Add(2, myList);
I tried this code but it seems it doesn't do anything.
List<KeyValuePair<int, List<int>>> myList2 = myDic.ToList();
myList2.Sort((firstPair, nextPair) =>
{
return firstPair.Value.Where(i=>i==1).Sum().CompareTo(nextPair.Value.Where(x=>x==1).Sum());
});
You are sorting list items in ascending order. I.e. items with more 1s will go to the end of list. You should use descending order. Just compare nextPair to firstPair (or change sign of comparison result):
myList2.Sort((firstPair, nextPair) =>
{
return nextPair.Value.Where(i => i==1).Sum().CompareTo(
firstPair.Value.Where(x => x==1).Sum());
});
This approach has one problem - sum of 1s in value will be calculated each time two items are compared. Better use Enumerable.OrderByDescending. It's more simple to use, and it will compute comparison values (i.e. keys) only once. Thus Dictionary is a enumerable of KeyValuePairs, you can use OrderByDescending directly with dictionary:
var result = myDic.OrderByDescending(kvp => kvp.Value.Where(i => i == 1).Sum());
Your sort is backward, which is why you think it's not doing anything. Reverse the firstPair/nextPair values in your lambda and you'll get the result you expect.
Though, #Sergey Berezovskiy is correct, you could just use OrderBy, your example code could benefit from perhaps a different pattern overall.
class SummedKV
{
public KeyValuePair Kvp {get; set;}
public int Sum {get; set;}
}
var myList =
myDic.ToList()
.Select(kvp=> new SummedKV {Kvp = kvp, Sum = kvp.Value.Sum() });
myList.Sort(skv=>skv.Sum);
Maybe something simpler
myList2.OrderByDescending(x => x.Value.Sum());
Your code does do something. it creates a list of the items that used to be in the dictionary, sorted based on the number of 1 items contained in the list. The code that you have correctly creates this list and sorts it as your requirements say it should. (Note that using OrderByDescending would let you do the same thing more simply.)
It has no effect on the dictionary that you pulled the lists out of, of course. Dictionaries are unordered, so you can't "reorder" the items even if you wanted to. If it were some different type of ordered collection then it would be possible to change the order of it's items, but just creating a new structure and ordering that wouldn't do it; you'd need to use some sort of operation on the collection itself to change the order of the items.
I was asked the following question in an interview. How can I sort a Dictionary by the key, in the order which is in an array list.
So for example I have a dictionary as follows
Dictionary<string, string> stringDict = new Dictionary<string, string>();
stringDict.Add("1", "One");
stringDict.Add("7", "Seven");
stringDict.Add("6", "Six");
stringDict.Add("2", "Two");
stringDict.Add("3", "Three");
stringDict.Add("5", "Five");
stringDict.Add("4", "Four");
And an array list as follows
ArrayList stringArList = new ArrayList();
stringArList.Add("1");
stringArList.Add("2");
stringArList.Add("3");
stringArList.Add("5");
stringArList.Add("6");
stringArList.Add("7");
stringArList.Add("4");
How can I sort the dictionary in the order it is in the array list?
Well you can't sort a Dictionary per se, but you can extract the key-values pairs as a list and sort those:
IEnumerable<KeyValuePair<string, string>> pairs =
stringDict.OrderBy(kvp => stringArList.IndexOf(kvp.Key));
But there's not a way to "traverse" dictionary items in any particular order.
You could create a SortedDictionary and provide an IComparer<string>
var d = new SortedDictionary<string, string>(stringDict,
new PositionComparer(stringArList));
With the Comparer implementation as:
public class PositionComparer : IComparer<string>
{
private ArrayList Keys {get; set;}
public PositionComparer(ArrayList keys)
{
Keys = keys;
}
public int Compare(string s1, string s2)
{
return Keys.IndexOf(s1).CompareTo(Keys.IndexOf(s2));
}
}
This will produce a list of the values sorted as required.
var sortedValues = stringDict.OrderBy(pair => stringArList.IndexOf(pair.Key))
.Select(pair => pair.Value)
.ToList();
As said many times before in this question, a C# Dictionary can not be sorted. This is inherent to the implementation. As you can read here, the dictionary is implemented using a Hashtable. This means that those items don't have any ordering. You can't say "give me the first element of this dictionary". There simply is no first, second or last element. The only thing you can say about an element in a dictionary is that it has a unique identifier which determines it's location in the dictionary (with a little help from the hash function).
When you have an element in an array for example, you can say "this element is the next element" or "this element is the previous element". Each element in an array has a previous and a next. This does not hold for dictionaries.
When you insert an item into the dictionary it will generate a hash (a fairly unique number) based on the key. For example, a very simple (and bad) hash of keys consisting of names would be to take the sum of each character presented as their ASCII value in the name, and then add those together. The result is a number, say 5, then we would insert the value in a store (an array for example) on position 5. If however, at position 5 is another value, which happens to have the same hash result you have a collision. How you solve these, and how you avoid these is what hashtables are all about. See the Wiki for more information on this.
When you request your value with your key someName it will hash that value and look it up at that position.
Hashtables are not as easy as I just explained, there is a lot too it. You can read more on the Wiki.
So the answer to "Sort this dictionary" is most definitely "No can do.". However, you can convert it to a sortable data structure like a list, or whatever and then sort it.
I replied with the following answer.
var list = from arElement in stringArList.ToArray().ToList()
join dict in stringDict on arElement equals dict.Key
select dict ;
But the interviewer didn't seem to be impressed.
original_dic.OrderBy returns IOrderedEnumerable, that you convert to a new dictionary.
var ordered_dic = original_dic.OrderBy(x => x.Key).ToDictionary(x=> x.Key, x=> x.Value);
I have tried to sort a Dictionary object by value which is generic.
Here is my code
Dictionary<string, ReportModel> sortedDic = new Dictionary<string, ReportModel>();
Dictionary<string, ReportModel> rDic = new Dictionary<string, ReportModel>();
var ordered = sortedDic.OrderByDescending(x => x.Value.totalPurchase);
foreach (var item in ordered)
{
rDic.Add(item.Key, item.Value);
}
The variable, ordered, just has the same order like sortedDic.
What is wrong with this?
Any idea?
This happens because Dictionary is generally an unordered container*. When you put the data into rDic, it becomes unordered again.
To retain the desired order, you need to put the results into a container that explicitly keeps the ordering that you supply. For example, you could use a list of KeyValuePair<string,ReportModel>, like this:
IList<KeyValuePair<string,ReportModel>> ordered = sortedDic
.OrderByDescending(x => x.Value.totalPurchase)
.ToList();
* Due to the way the Dictionary<K,V> is implemented by Microsoft, it happens to retain the insertion order, but that is incidental and undocumented, so it may change in the future versions, and should not be relied upon.
When adding the items back to the dictionary, it would not keep their order.
You can either:
Use the following implementation.
Use a list in the below form.
IEnumrable> lst=
sortedDic.OrderByDescending(x => x.Value.totalPurchase).ToArray();
[EDIT] If you don't mind the key changing then you can use SortedDictionary<,>.
I have a Collection object (based on System.Collections.CollectionBase) but to access the values of objects within that collection, I have to use the index currently. Is it possible to get the values based on the name of the object within the collection?
For example, instead of...
MyCollection[0].Value
... how can I do something along the lines of:
MyCollection["Birthday"].Value
In order to do this you would need to have a Dictionary<string,object>. Unfortunately collections only allow random access by index.
You could do something like this:
var item = MyCollection
.Where(x => x.SomeProp == "Birthday")
.FirstOrDefault();
// careful - item could be null here
var value = item.Value;
But this will be nowhere near as efficient as random access by index.
You could use a Dictionary<TKey, TValue> which allows you to access its element by a key. So if the key in your example is a string you could use Dictionary<string, TValue>.
Why do you think objects in a collection have names? They don't. What you can do is use a Dictionary<String, SomethingElse> to enable your syntax.
As others has said, you need a Dictionary<> to do that. If you cannot change the code that provides the collection, you can use LINQ's ToDictionary() method to convert it to a dictionary yourself:
var dict = MyCollection.ToDictionary(obj => obj.Name);
From there on, you can do:
var value = dict["Birthday"].Value;
You could use the this[] accessor
public Item this[string name]
{
get
{
// iterate through the elements of the collection
//and return the one that matches with name
}
}
Have this getter property on your MyCollectionClass
One workaround could be
private const int BIRTHDAY = 0;
var value = MyCollection["Birthday"].Value;