Get the last element in a dictionary? - c#

My dictionary:
Dictionary<double, string> dic = new Dictionary<double, string>();
How can I return the last element in my dictionary?

What do you mean by Last? Do you mean Last value added?
The Dictionary<TKey,TValue> class is an unordered collection. Adding and removing items can change what is considered to be the first and last element. Hence there is no way to get the Last element added.
There is an ordered dictionary class available in the form of SortedDictionary<TKey,TValue>. But this will be ordered based on comparison of the keys and not the order in which values were added.
EDIT
Several people have mentioned using the following LINQ style approach
var last = dictionary.Values.Last();
Be very wary about using this method. It will return the last value in the Values collection. This may or may not be the last value you added to the Dictionary. It's probably as likely to not be as it is to be.

Dictionaries are unordered collections - as such, there is no concept of a first or last element. If you are looking for a class that behaves like a dictionary but maintains the insertion order of items, consider using OrderedDictionary.
If you are looking for a collection that sorts the items, consider using SortedDictionary<TKey,TValue>.
If you have an existing dictionary, and you are looking for the 'last' element given some sort order, you could use linq to sort the collection, something like:
myDictionary.Values.OrderBy( x => x.Key ).Last();
By wary of using Dictionary.Keys.Last() - while the key list is sorted using the default IComparer for the type of the key, the value you get may not be the value you expect.

I know this question is too old to get any upvotes, but I didn't like any of the answers so will post my own in the hopes of offering another option to future readers.
Assuming you want the highest key value in a dictionary, not the last inserted:
The following did not work for me on .NET 4.0:
myDictionary.Values.OrderBy( x => x.Key ).Last();
I suspect the problem is that the 'x' represents a value in the dictionary, and a value has no key (the dictionary stores the key, the dictionary values do not). I may also be making a mistake in my usage of the technique.
Either way, this solution would be slow for large dictionaries, probably O(n log n) for CS folks, because it is sorting the entire dictionary just to get one entry. That's like rearranging your entire DVD collection just to find one specific movie.
var lastDicVal = dic.Values.Last();
is well established as a bad idea. In practice, this solution may return the last value added to the dictionary (not the highest key value), but in software engineering terms that is meaningless and should not be relied upon. Even if it works every time for the rest of eternity, it represents a time bomb in your code that depends on library implementation detail.
My solution is as follows:
var lastValue = dic[dic.Keys.Max()];
The Keys.max() function is much faster than sorting O(n) instead of O(n log n).
If performance is important enough that even O(n) is too slow, the last inserted key can be tracked in a separate variable used to replace dic.Keys.Max(), which will make the entire lookup as fast as it can be, or O(1).
Note: Use of double or float as a key is not best practice and can yield surprising results which are beyond the scope of this post. Read about "epsilon" in the context of float/double values.

If you're using .NET 3.5, look at:
dic.Keys.Last()
If you want a predictable order, though, use:
IDictionary<int, string> dic = new SortedDictionary<int, string>();

Instead of using:
Dictionary<double, string>
...you could use:
List<KeyValuePair<double, string>>
This would allow you to use the indexer to access the element by order instead of by key.

Consider creating a custom collection that contains a reference in the Add method of the custom collection. This would set a private field containing the last added key/value(or both) depending on your requirements.
Then have a Last() method that returns this. Here's a proof of concept class to show what I mean (please don't knock the lack of interface implementation etc- it is sample code):
public class LastDictionary<TKey, TValue>
{
private Dictionary<TKey, TValue> dict;
public LastDictionary()
{
dict = new Dictionary<TKey, TValue>();
}
public void Add(TKey key, TValue value)
{
LastKey = key;
LastValue = value;
dict.Add(key, value);
}
public TKey LastKey
{
get; private set;
}
public TValue LastValue
{
get; private set;
}
}

From the docs:
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.
So, I don't think you can rely on Dictionary to return the last element.
Use another collection. Maybe SortedDictionary ...

If you just want the value, this should work (assuming you can use LINQ):
dic.Values.Last()

You could use:
dic.Last()
But a dictionary doesn't really have a last element (the pairs inside aren't ordered in any particular way). The last item will always be the same, but it's not obvious which element it might be.

With .Net 3.5:
string lastItem = dic.Values.Last()
string lastKey = dic.Keys.Last()
...but keep in mind that a dictionary is not ordered, so you can't count on the fact that the values will remain in the same order.

A dictionary isn't meant to be accessed in order, so first, last have no meaning. Do you want the value indexed by the highest key?
Dictionary<double, string> dic = new Dictionary<double, string>();
double highest = double.MinValue;
string result = null;
foreach(double d in dic.keys)
{
if(d > highest)
{
result = dic[d];
highest = d;
}
}

Instead of using Linq like most of the other answers suggest, you can just access the last element of any Collection object via the Count property (see ICollection.Count Property for more information).
See the code here for an example of how to use count to access the final element in any Collection (including a Dictionary):
Dictionary<double, string> dic = new Dictionary<double, string>();
var lastElementIndex = dic.Count - 1;
var lastElement = dic[lastElementIndex];
Keep in mind that this returns the last VALUE, not the key.

Related

How to search first occurrence of string key in c# dictionary without LINQ

I have data in a dictionary in this way:
Dictionary<string, cls_CTCs> dict = new Dictionary<string, cls_CTCs>();
dict.Add("9814|30500994",Obj);
dict.Add("41377|30302099",Obj);
dict.Add("65793|30500337",Obj);
dict.Add("92894|30300795",Obj);
dict.Add("92894|30300826",Obj);
dict.Add("92894|30300827",Obj);
dict.Add("92894|30300828",Obj);
dict.Add("56936|30300894",Obj);
dict.Add("56936|30300365",Obj);
dict.Add("56936|30300485",Obj);
Where key is string type and value is an object of a class. I want to find first occurrence of a string in all the keys of this dictionary in like or startswith pattern. For example, if I search for "92894", then it should return the key "92894|30300795" and if I search for "56936", then it should return the key "56936|30300894".
I know it could be done easily by using LINQ, but I dont want to use LINQ as I would use this code in C# CLR Stored Procedure which does not allow LINQ. So, is there any extension method or any other approach that I could achieve what I want?
You can use Dictionary.Keys which returns all keys in the dictionary.
However the order of Keys in a dictionary is undefined, so finding the first one has no meaning - it will return any key that matches, at random.
// Returns a key which starts with prefix, or null if not found.
public string FindKey<T>(Dictionary<string, T> dict, string prefix)
{
foreach (string key in dict.Keys)
{
if (key.StartsWith(prefix))
return key;
}
return null;
}
Unfortunately, there is no other way for achieving it without a full iterative scan over the dictionary.
The reason is how the current implementation of a Dictionary<TKey, TValue> internally works. All the keys are indexed using their hash codes (see the Object.GetHashCode method). So there is a fast and effective search of a key as a whole object only.
If you need to find some keys by a partial match (StartsWith or whatever), you just need to iterate over each key performing a comparison/lookup.
You can do it either using the dictionary's Keys collection or just iterating over the dictionary itself working with the KeyValuePair<TKey, TValue> objects.
Keep in mind that there is no particular order, however. So "the first occurrence" might be a requirement that is hard do fulfill.
You might want to use an OrderedDictionary if the objects' order is important.

Hashtable scrambling?

I have the following hashtable on my application:
System.Collections.Hashtable colunas = new System.Collections.Hashtable();
colunas.Add("Nome", "Nome");
colunas.Add("Departamento", "Departamento");
colunas.Add("Cargo", "Cargo");
After, I pass this hashtable as parameter to a function and when I pass through the hashtable in a foreach I get the following results:
Departamento
Nome
Cargo
Why the result is in that order and not in this:
Nome
Departamento
Cargo
-- EDIT --
Ok, I understood the reason, but what can I use instead of hashtable to preserve the insertion order?
Hashtables do not preserve insertion order.
Instead, they use an unspecified order based on the hashcodes of the keys.
This answer is "promoted" from a comment, by request from the Original Poster.
If it is important for you to keep the order of insertion, you might want to simply use a List<> whose elements are somehow pairs of strings. Two solutions are natural, either:
var colunas = new List<KeyValuePair<string, string>>();
colunas.Add(new KeyValuePair<string, string>("Nome", "Nome"));
colunas.Add(new KeyValuePair<string, string>("Departamento", "Departamento"));
colunas.Add(new KeyValuePair<string, string>("Cargo", "Cargo"));
or:
var colunas = new List<Tuple<string, string>>();
colunas.Add(Tuple.Create("Nome", "Nome"));
colunas.Add(Tuple.Create("Departamento", "Departamento"));
colunas.Add(Tuple.Create("Cargo", "Cargo"));
There's a technical difference between KeyValuePair<,> and Tuple<,> because the former is a struct (value type) and the latter is a class (reference type), but since both KeyValuePair<,> and Tuple<,> are immutable types, that is probably unimportant. Then decide if the property names Key/Value or Item1/Item2 are best suited for your use.
Note that if you use this solution, you don't get the benefits a hashtable offers. You don't get fast lookup on key. And there's no guarantee that the List<> can't have many entries with the same "key" string (first component of the pair). That string could even be null.
If you want to sort the List<> after all, at some point, the call colunas.Sort(); (no comparer argument given) will work for Tuple<,> (lexicographic order) but not for KeyValuePair<,>. Of course if you wanted the collection sorted all the time by keys, you would use SortedDictionary<string, string> as suggested by another answer.
Hashtable represents a collection of key/value pairs that are organized based on the hash code of the key.
but what can I use instead of hashtable to preserve the insertion order?
You have a choice:
System.Collections.Generic.SortedList<TKey, TValue>
System.Collections.Generic.SortedDictionary<TKey, TValue>
See the remarks section here for the differences.

Difference between Dictionary and Hashtable [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why Dictionary is preferred over hashtable in C#?
What is the difference between Dictionary and Hashtable. How to decide which one to use?
Simply, Dictionary<TKey,TValue> is a generic type, allowing:
static typing (and compile-time verification)
use without boxing
If you are .NET 2.0 or above, you should prefer Dictionary<TKey,TValue> (and the other generic collections)
A subtle but important difference is that Hashtable supports multiple reader threads with a single writer thread, while Dictionary offers no thread safety. If you need thread safety with a generic dictionary, you must implement your own synchronization or (in .NET 4.0) use ConcurrentDictionary<TKey, TValue>.
Lets give an example that would explain the difference between hashtable and dictionary.
Here is a method that implements hashtable
public void MethodHashTable()
{
Hashtable objHashTable = new Hashtable();
objHashTable.Add(1, 100); // int
objHashTable.Add(2.99, 200); // float
objHashTable.Add('A', 300); // char
objHashTable.Add("4", 400); // string
lblDisplay1.Text = objHashTable[1].ToString();
lblDisplay2.Text = objHashTable[2.99].ToString();
lblDisplay3.Text = objHashTable['A'].ToString();
lblDisplay4.Text = objHashTable["4"].ToString();
// ----------- Not Possible for HashTable ----------
//foreach (KeyValuePair<string, int> pair in objHashTable)
//{
// lblDisplay.Text = pair.Value + " " + lblDisplay.Text;
//}
}
The following is for dictionary
public void MethodDictionary()
{
Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary.Add("cat", 2);
dictionary.Add("dog", 1);
dictionary.Add("llama", 0);
dictionary.Add("iguana", -1);
//dictionary.Add(1, -2); // Compilation Error
foreach (KeyValuePair<string, int> pair in dictionary)
{
lblDisplay.Text = pair.Value + " " + lblDisplay.Text;
}
}
There is one more important difference between a HashTable and Dictionary. If you use indexers to get a value out of a HashTable, the HashTable will successfully return null for a non-existent item, whereas the Dictionary will throw an error if you try accessing a item using a indexer which does not exist in the Dictionary
Dictionary is typed (so valuetypes don't need boxing), a Hashtable isn't (so valuetypes need boxing). Hashtable has a nicer way of obtaining a value than dictionary IMHO, because it always knows the value is an object. Though if you're using .NET 3.5, it's easy to write an extension method for dictionary to get similar behavior.
If you need multiple values per key, check out my sourcecode of MultiValueDictionary here:
multimap in .NET
Want to add a difference:
Trying to acess a inexistent key gives runtime error in Dictionary but no problem in hashtable as it returns null instead of error.
e.g.
//No strict type declaration
Hashtable hash = new Hashtable();
hash.Add(1, "One");
hash.Add(2, "Two");
hash.Add(3, "Three");
hash.Add(4, "Four");
hash.Add(5, "Five");
hash.Add(6, "Six");
hash.Add(7, "Seven");
hash.Add(8, "Eight");
hash.Add(9, "Nine");
hash.Add("Ten", 10);// No error as no strict type
for(int i=0;i<=hash.Count;i++)//=>No error for index 0
{
//Can be accessed through indexers
Console.WriteLine(hash[i]);
}
Console.WriteLine(hash["Ten"]);//=> No error in Has Table
here no error for key 0 & also for key "ten"(note: t is small)
//Strict type declaration
Dictionary<int,string> dictionary= new Dictionary<int, string>();
dictionary.Add(1, "One");
dictionary.Add(2, "Two");
dictionary.Add(3, "Three");
dictionary.Add(4, "Four");
dictionary.Add(5, "Five");
dictionary.Add(6, "Six");
dictionary.Add(7, "Seven");
dictionary.Add(8, "Eight");
dictionary.Add(9, "Nine");
//dictionary.Add("Ten", 10);// error as only key, value pair of type int, string can be added
//for i=0, key doesn't exist error
for (int i = 1; i <= dictionary.Count; i++)
{
//Can be accessed through indexers
Console.WriteLine(dictionary[i]);
}
//Error : The given key was not present in the dictionary.
//Console.WriteLine(dictionary[10]);
here error for key 0 & also for key 10 as both are inexistent in dictionary, runtime error, while try to acess.
The Hashtable class is a specific type of dictionary class that uses an integer value (called a hash) to aid in the storage of its keys. The Hashtable class uses the hash to speed up the searching for a specific key in the collection. Every object in .NET derives from the Object class. This class supports the GetHash method, which returns an integer that uniquely identifies the object. The Hashtable class is a very efficient collection in general. The only issue with the Hashtable class is that it requires a bit of overhead, and for small collections (fewer than ten elements) the overhead can impede performance.
There is Some special difference between two which must be considered:
HashTable: is non-generic collection ,the biggest overhead of this
collection is that it does boxing automatically for your values and
in order to get your original value you need to perform unboxing ,
these to decrease your application performance as penalty.
Dictionary: This is generic type of collection where no implicit
boxing, so no need to unboxing you will always get your original
values which you were stored so it will improve your application
performance.
the Second Considerable difference is:
if your were trying to access a value on from hash table on the basis
of key that does not exist it will return null.But in the case of
Dictionary it will give you KeyNotFoundException.
ILookup Interface is used in .net 3.5 with linq.
The HashTable is the base class that is weakly type; the DictionaryBase
abstract class is stronly typed and uses internally a HashTable.
I found a a strange thing about Dictionary, when we add the multiple entries in Dictionary, the order in which the entries are added is maintained. Thus if I apply a foreach on the Dictionary, I will get the records in the same order I have inserted them.
Whereas, this is not true with normal HashTable, as when I add same records in Hashtable the order is not maintained. As far as my knowledge goes, Dictionary is based on Hashtable, if this is true, why my Dictionary maintains the order but HashTable does not?
As to why they behave differently, it's because Generic Dictionary implements a hashtable, but is not based on System.Collections.Hashtable. The Generic Dictionary implementation is based on allocating key-value-pairs from a list. These are then indexed with the hashtable buckets for random access, but when it returns an enumerator, it just walks the list in sequential order - which will be the order of insertion as long as entries are not re-used.
shiv govind
Birlasoft.:)

How can I retrieve first n elements from Dictionary<string, int>?

Is there a way to retrieve first n elements from a Dictionary in C#?
Dictionaries are not ordered per se, you can't rely on the "first" actually meaning that. From MSDN: "For enumeration... The order in which the items are returned is undefined."
You may be able to use an OrderedDictionary depending on your platform version, and it's not a particularly complex thing to create as a custom descendant class of Dictionary.
Oftentimes omitting the cast to dictionary won't work:
dictionary = dictionary.Take(n);
And neither will a simple case like this:
dictionary = dictionary.Take(n).ToDictionary();
The surest method is an explicit cast:
dictionary = dictionary.Take(n).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
Note that there's no explicit ordering for a Dictionary, so although the following code will return n items, there's no guarantee as to how the framework will determine which n items to return.
using System.Linq;
yourDictionary.Take(n);
The above code returns an IEnumerable<KeyValuePair<TKey,TValue>> containing n items. You can easily convert this to a Dictionary<TKey,TValue> like so:
yourDictionary.Take(n).ToDictionary();
You can't really take the first N elements from a Dictionary<TKey,TValue> because it is not an ordered collection. So it really has no concept of First, Last, etc ... But as others have pointed out, if you just want to take N elements regardless of order the LINQ take function works fine
var map = GetTheDictionary();
var firstFive = map.Take(5);
Could use Linq for example?
var dictionary = new Dictionary<string, int>();
/// Add items to dictionary
foreach(var item in dictionary.Take(5))
{
// Do something with the first 5 pairs in the dictionary
}

How do I get all the values of a Dictionary<TKey, TValue> as an IList<TValue>?

I have a the following dictionary:
IDictionary<int, IList<MyClass>> myDictionary
and I am wanting to get all the values in the dictionary as an IList....
Just to add a bit of a background as to how I've gotten into this situation....
I have a method that gets me a list of MyClass. I then have another method that converts that list into a dictionary where they key is the id for MyClass. Later on...and without access to that original list...I'm needing to obtain the original ungrouped list of MyClass.
When I pass myDictionary.Values.ToList() to a method that takes an IList I get a compile error that says that it can't convert from
System.Collections.Generic.List<System.Collections.Generic.IList<MyClass>>
to:
System.Collections.Generic.IList<MyClass>
Now, I can understand that its gone and added each of the groups of IList to the new list as separate elements of the list....but in this instance its not really what I'm after. I just want a list of all the values in the entire dictionary.
How then can I get what I'm after without looping through each of the key values in the dictionary and creating the list I want?
Noticed a lot of answer were quite old.
This will also work:
using System.Linq;
dict.Values.ToList();
Because of how a dictionary (or hash table) is maintained this is what you would do. Internally the implementation contains keys, buckets (for collision handling) and values. You might be able to retrieve the internal value list but you're better of with something like this:
IDictionary<int, IList<MyClass>> dict;
var flattenList = dict.SelectMany( x => x.Value );
It should do the trick ;) SelectMany flattens the result which means that every list gets concatenated into one long sequence (IEnumerable`1).
A variation on John's suggestion:
var flattenedValues = dict.Values.SelectMany(x => x);
If you need them in a list, you can of course call ToList:
var flattenedList = dict.Values.SelectMany(x => x).ToList();
dictionary.values.toList();
if You want to get Sum just do
myDictionary.values.sum();
Values gets a ICollection containing the values of your dictionary. As implied by the definition of your dictionary, it can be defined as a ICollection<IList<MyClass>> collection. So if you really want a IList<IList<MyClass>>, use spacedog's solution.
If what you really want is a flat `IList', then there is no other solution than looping through each value :
IList<MyClass> l=new List<MyClass>();
foreach (IList<MyClass> v in myDictionary.Values)
l.AddRange(v);
Note that this is so grossly inefficient that you should think again about using a dictionary for what you are trying to achieve.

Categories