How to get a partilcular item from a Dictionary object with index? - c#

How to retrive an item from an dictionary object using an Index? eg i have a dicitiory object of 10 items and i have to get the 5th keypairvalue from the dictionary?

Dictionaries are unordered. If you mean "the 5th item added to the dictionary" - they don't provide this functionality.
One thing to be careful of is that in many cases Dictionary<TKey, TValue> appears to be ordered - if you just add a bunch of entries and then iterate, then under the current implementation I believe you will at least usually get back the pairs in the same order. However, it's not guaranteed, it's not meant to happen particularly - it's just a quirk of the implementation. If you delete entries and then add more, then the whole thing goes pear-shaped.
Fundamentally, if you want ordering as well as key lookups, you need to store a list as well as a dictionary.

If you are using .NET 3.5 or greater:
var keyValuePair = d.ElementAt(4);
However, this is using an enumerator behind the scenes and the ordering of enumerated items from a dictionary is not guaranteed:
The IDictionary interface allows the contained keys and values to be enumerated, but it does not imply any particular sort order (From IDictionary reference on MSDN).
This means that the element you get back might not correspond to the order you inserted it in and thus is probably not what you expect.
There is an OrderedDictionary class in System.Collections.Specialized that enforces the ordering and allows you to access by index through the Item indexer. However, this is from the pre-generics days so it only accepts object key-values and thus isn't quite as friendly to work with as the generic collections.
I just found this article on CodeProject that implements a generic OrderedDictionary. I have never used this but it might be useful for you.

Ignoring the fundamental abuse of a dictionary that this question presents:
int counter = 0;
foreach (var pair in yourDictionary)
{
if (++counter == 5)
{
// pair contains your fifth item
}
}

If you're using a generic dictionary like this:
Dicionary<int,string> myDict = new Dictionary<int,string>();
You could pull the 5th value from the dictionary by converting the output to a list:
string SomeString = myDict.Values.ToList()[4];
But typically you'd use a dictionary when you're more concerned about retrieving a value based on a pre-determined key rather than it's position in the list.

The 5th according to which ordering? The Dictionary class does not guarantee any specific ordering. If you want it in some specific ordering, retrieve the pairs from the collection (for example as John suggests) and sort them, then get the KeyValuePair at the index you need. If you need it ordered by insertion order, try using the System.Collections.Specialized.OrderedDictionary instead, then you can access the KeyValuePair directly by index.

Use System.Linq
string item=dicOBj.Keys.ElementAt(index);
you can get both key and value in the same way specifying index

.NET Framework has 8 dictionary classes: Dictionary, Hastable, ListDictionary, OrderedDictionary, SortedDictionary , SortedList, SortedList Generic. In all these classes items can be retrieved by key, but items can be retrieved by index only in OrderedDictionary, SortedList, SortedList Generic. If you need to retrieve from you dictionary items by key or by index you must use one of these classes: OrderedDictionary, SortedList, SortedList Generic.
How to use these classes you can find: OrderedDictionary Class , SortedList Class

Related

What are the differences between a list, sorted list, and an array list? (c#)

From what I've read, a list, sorted list, and an array list have many things in common, but at the same time have a few differences.
I would like to know: What are the differences between them that a beginner should know? Why choose one over the other? And what are some good habits to form when using them in code?
Thank you for your time.
From MSDN:
A SortedList element can be accessed by its key, like an element in
any IDictionary implementation, or by its index, like an element in
any IList implementation.
A SortedList object internally maintains two arrays to store the
elements of the list; that is, one array for the keys and another
array for the associated values. Each element is a key/value pair that
can be accessed as a DictionaryEntry object. A key cannot be null, but
a value can be.
Also for choosing best collection you can see this.
with List<T> and SortedList<T> you can specify the type of the element and are generally easier to use because of that. ArrayList is legacy, and holds objects but you must cast them to the contained type yourself.
SortedList<T> as the name implies is a sorted list of type T. Use it when you want a sorted list. Use List<T> when a sorted ordering is unnecessary or when a general collection of T is sufficient or you provide your own sorting mechanism. SortedList<T> will be slower on adding items then List<T>, so only use it when necessary.

How does C# SortedList internally work?

I was wondering, how does the SortedList work.
I know that a regular List is based on a dynamic array, but what is SortedList based on?
And what sorting algorithm it uses?
Thanks
From the sortedlist documentation: "SortedList is implemented as an array of key/value pairs, sorted by the key."
http://msdn.microsoft.com/en-us/library/e7a8xew6%28v=vs.110%29.aspx
If you use the default constructor (no parameters): "Initializes a new instance of the SortedList class that is empty, has the default initial capacity, and is sorted according to the IComparable interface implemented by each key added to the SortedList object."
http://msdn.microsoft.com/en-us/library/cxb97few%28v=vs.110%29.aspx
Or you can pass a custom comparer:
Initializes a new instance of the SortedList class that is empty, has the default initial capacity, and is sorted according to the specified IComparer interface.
http://msdn.microsoft.com/en-us/library/e7a8xew6%28v=vs.110%29.aspx
Other constructor options:
http://msdn.microsoft.com/en-us/library/System.Collections.SortedList.SortedList%28v=vs.110%29.aspx
How to use IComparer interface: http://msdn.microsoft.com/en-us/library/system.collections.icomparer%28v=vs.110%29.aspx
SortedList class source code can be found here.
According to this source, SortedList keeps data in two plain arrays of keys and values:
private TKey[] keys;
private TValue[] values;
Sort order is maintained on the array of keys. When a new item (key/value pair) is added, SortedList first finds proper index in the sorted array of keys (using Array.BinarySearch), then moves partial contents of both key and value arrays (using Array.Copy) starting from this index upward to create a gap where both key and value are inserted. Likewise, when an item is deleted by its key, SortedList searches for the item's index in the array of keys, then moves partial contents of both arrays from this index downward to close the gap.
So, one thing to keep in mind is that when adding to or deleting from a large SortedList, a lot of data may be moved around. On the positive side, retrieving items by index is always fast regardless of the list size.
A SortedList is an object that maintain's two array to store the element's of the list.
One array store's the Key and the other array store's its associated values.
The element's in the SortedList are sorted either according to a specific IComparer implementation specified when the SortedList is created or according to the IComparable implementation provided by the keys themselves. They cannot contain duplicate keys.
Whenever any element is added or removed the index is adjusted accordingly as a result operations related to SortedList are slower.
If you are interested in the internals of how it works, get yourself any half decent decompiler, such as .Net Reflector.
A quick look shows that internally, SortedList maintains it's sorted state by keeping an internal array sorted at all times. When an item is added using the Add Method, it uses a binary search on the keys to identify the correct index to insert the new item.

Is a HashSet<T> the same as List<T> but with uniqueness?

I need to have an ability to have unique items in a collection.
I was going to use a Dictionary so I could use the ContainsKey method but I thought it would be a waste as I wouldnt use the Value property of the Key/Value pair.
I came across the HashSet<T> which looks very promising. The only thing I can find that I can't find in the List<T> docs is that HashSet<T> is unordered. I think that is fine, I assume it means its not ordered using a IEqualityComparer. As long as the order in which items are added are in the same index position I think it will be ok as I have to do duplicate checking hence the hashset and then check all entries are sequential.
Is there anything else I have missed comparing the two types?
No, importantly HashSet<T> doesn't have any concept of ordering or indexing - a list conceptually has slots 0....n-1, whereas a set is "just a set".
I think that is fine, I assume it means its not ordered using a IEqualityComparer.
IEqualityComparer isn't used for ordering anyway - it only talks about equality and hash codes. HashSet<T> isn't ordered by either an element comparison (as, say, SortedSet<T> is) or insertion order.
As long as the order in which items are added are in the same index position I think it will be ok.
There is no index position, and when you iterate over a HashSet<T> there's no guarantee you'll get them back in the order in which you added them. If you're even thinking about ordering, HashSet<T> isn't what you're after.
Then again, all of this is also true of Dictionary<TKey, TValue> - you shouldn't make any assumptions about ordering there, either.
This is a 'picture' of what a List<T> looks like:
List: |a|b|r|t|i|p|c|y|z|...
Index: |0|1|2|3|4|5|6|7|8|...
The List<T> represents, well, a list of items. You can refer to an item by its position in the list.
This is a 'picture' of what a HashSet<T> looks like:
Set: |a|b|c| | | | | |i| | | | | | |p| |r| |t| | | | |y|z|
Bucket: |a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|
The HashSet<T> represents a set of unique items. Every item has its own 'bucket'. You can refer to an item by its bucket. The bucket that an item belongs in is calculated directly from an item.
One of the advantages of using a HashSet over a List is constant-time searches. In a List, an item could be anywhere in the List, so to find it, you need to look at every item in the List. In a HashSet, there is only one possible location for any given item. Therefore, to search for an item, all you need to do is look in its bucket. If it's there, it's there, if it's not, it's not.
The illustrations may not be 100% accurate (for simplicity's sake). Especially the HashSet example.
No. A HashSet doesn’t allow access via index because the items aren’t ordered. This does not mean, as you suspect, that they aren’t ordered according to some IEqualityComparer. It means that they are not stored inside the hash set in the order of adding them.
So if you need an order preserving or random access container, HashSet is not for you.
It sounds like this is what you're after:
class UniqueList<T> : Collection<T>
{
protected override void InsertItem(int index, T item)
{
if (!base.Contains(item))
{
base.InsertItem(index, item);
}
else
{
// whatever
}
}
}
Calling UniqueList.Add will add an item to the end of the list, and will not add duplicate values.
Well HashSet conceptually is a List of unique values, but in difference from List<T> it doesn't actually implements IList interface, but implements ICollection.
Plus it has a set of special functions, like :
Intersection, IsSubsetOf, IsSupersetOf, Union, which List<T> doesn't have.
These functions, naturally, are handy in operations on multiple HasSets.
You got it slightly wrong. Neither Dictionary nor HashSet preserves the order of the items, this means you can't rely on the item index. Theoretically you can use LINQ ElementAt() to access item by index, but again both collections do not gurantee that order is preserved.
.NET provides an OrderedDictionary class, but it is not generic so you would not have a type safety at compile time. Anyways it allows accessing items by index.
Here is a custom implementation of the generic one: OrderedDictionary(of T): A generic implementation of IOrderedDictionary. The key point: it persists two collections -- List and Dictionary at the same time; List provides access by index and Dictionary provides fast access by a key.

Unexpected issue Copying Dictionaries

My idea was to copy a dictionary while resetting all the values of the previous one, so i have this instruction:
var dic2 = new Dictionary<string, int>(dic.ToDictionary(kvp => kvp.Key, kvp => 0));
However i had an unexpected problem doing this, since the new copied dictionary doesnt have the same order of keys of the previous one.
Any way to reset the values but to maintain the same order of keys? Witouth resorting to some type of sorting?
The answer is not to rely on the order of keys in a Dictionary<,> in the first place. It's emphatically not guaranteed.
This is documented on MSDN, but not nearly as clearly as I'd have wanted:
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.
.NET doesn't currently have an insertion-order-preserving dictionary implementation as far as I'm aware :(
The order of the keys in a Dictionary<K,V> isn't maintained. You might want to use a SortedDictionary<K,V> instead (note that this class sorts the entries based on the key, but doesn't allow an arbitrary order, unless you create a specific key comparer)
.Net dictionaries are unordered.
Your question has no answer.
You should consider using a List<KeyValuePair<string, int>> instead.
Dictionary doesn't define sequence of keys. It is not array or list. You should not rely on order of keys on dictionary. Dictionary was made for by-key access not for sequential.

C# associative array

I've been using a Hashtable, but by nature, hashtables are not ordered, and I need to keep everything in order as I add them (because I want to pull them out in the same order). Forexample if I do:
pages["date"] = new FreeDateControl("Date:", false, true, false);
pages["plaintiff"] = new FreeTextboxControl("Primary Plaintiff:", true, true, false);
pages["loaned"] = new FreeTextboxControl("Amount Loaned:", true, true, false);
pages["witness"] = new FreeTextboxControl("EKFG Witness:", true, true, false);
And when I do a foreach I want to be able to get it in the order of:
pages["date"]
pages["plaintiff"]
pages["loaned"]
pages["witness"]
How can I do this?
I believe that .NET has the OrderedDictionary class to deal with this. It is not generic, but it can serve as a decent Hashtable substitute - if you don't care about strict type safety.
I've written a generic wrapper around this class, which I would be willing to share.
http://msdn.microsoft.com/en-us/library/system.collections.specialized.ordereddictionary.aspx
EDIT: LBushkin is right - OrderedDictionary looks like it does the trick, albeit in a non-generic way. It's funny how many specialized collections there are which don't have generic equivalents :( (It would make sense for Malfist to change the accepted answer to LBushkin's.)
(I thought that...) .NET doesn't have anything built-in to do this.
Basically you'll need to keep a List<string> as well as a Dictionary<string,FreeTextboxControl>. When you add to the dictionary, add the key to the list. Then you can iterate through the list and find the keys in insertion order. You'll need to be careful when you remove or replace items though.
use sorted list i think it will solve your problem
becuase SortedList object internally maintains two arrays to store the elements of the list; that is, one array for the keys and another array for the associated values. Each element is a key/value pair that can be accessed as a DictionaryEntry object
SortedList sl = new SortedList();
foreach(DictionaryEntry x in sl)
{}
Use the KeyedCollection
Its underlying base is a List but provides a dictionary lookup based on key. In this case your key is the strings. So as long as you aren't adding the same key twice you are fine.
http://msdn.microsoft.com/en-us/library/ms132438.aspx
There's no perfect solution before .NET 4.0. In < 3.5 You can:
Use a generic SortedList with integer key-type, and value type of the most-derived common type of your items. Define an integer value (i, let's say) and as you add each item to the SortedList, make the key i++, incrementing it's value as you go. Later, iterate over the GetValueList property of the sorted list. This IList property will yield your objects in the order you put them in, because they will be sorted by the key you used.
This is not lightening-fast, but pretty good, and generic. If you want to also access by key, you need to do something else, but I don't see that in your requirements. If you don't new to retrieve by key, and you add items in key order so the collection doesn't actually have to do its sorting, this is it.
In .NET 4.0 you'll have the generic SortedSet Of T, which will be absolutely perfect for you. No tradeoffs.
The best way is to use the C# indexers. It is configurable to anything we like. We can pass an int, enum, long, double or anything we like.
Just have to create a class and give it indexers and configure input and output parameters. It is a little more work but I think this is the only right way.
Please see this MSDN link for more information how to use it.
See Indexers: http://msdn.microsoft.com/en-us/library/6x16t2tx.aspx
One alternative is to keep your ordered key values in an ordered structure like a List, the rest being still stored in a dictionnary.
Then, when you need to access your data, just go through your sorted List and query your dictionnary along the way.
look at sorted list
http://msdn.microsoft.com/en-us/library/system.collections.sortedlist.aspx
As Haxelit suggests, you might derive from KeyedCollection<TKey, TValue>. It actually uses a List underneath until you hit a certain threshold value, and then it maintains both a List and a Dictionary. If you can use a function to derive one of your keys from one of your values, then this is an easy solution. If not, then it gets pretty messy.

Categories