How to find a 'first' value in a Dictionary? - c#

How can I find the first value in a Dictionary<int, MyTableClass> where MyTableClass inherits Field<F1, F2, F3>? I'd prefer a Property or Property/Method combination that returns the first value in the Dictionary where F1 = MyEnum.value.
What I don't want to do is a foreach. Performance-wise, this is really not a preferred method.

The shortest way to find a value matching some criteria (I couldn't quite understand what you want specifically - first F1 is a generic type parameter, and then you use == to compare it as if it was a value...) is to do this:
dictionary.Values.First(x => ...);
where ... will be a boolean expression on x. However, this will not be any faster than foreach ...because you're not doing a lookup on dictionary key. Only key lookup is fast; for anything else, you have to do a linear scan (or maintain a second dictionary for a different key, which will be whatever you do lookups on). [copied from comment]

No matter how you dress it up here you are going to essentially have to do a foreach over the values in the Dictionary. A Dictionary<TKey,TValue> provides close to O(1) access for a full key to a given value. It is not designed to provide efficient access to a partial key. In order to get that you would need to keep a second Dictionary instance making the appropriate mapping.

The dictionary doesn't maintain any specific order between element, so there isn't really any element that can be the first one unless you specify some ordering.
You can get the first item that the dictionary happens to find like this:
MyTableClass one = dict.Where(pair => pair.Value.F1 == MyEnum.value).First();
This will just loop through the items until it finds a match, so you are just using the dictionary as a list. If you want any performance, you should have a dictionary where the value from F1 is the key.

You could use the .First() extension method.

Related

Use List or Dictionary?

I have a program where i need to store a list of some variables.
each variables has a name and a value and i want to make a function that gets the name of a variable and returns its value:
object getValue(string name);
To do that i have two choices:
1: Store the variables in a dictionary Dictionary and then the function getValue would just fetch the variable whose key is the name i am looking for:
object getValue (string name)
{
return variablesDictionary[name].Value;
}
2: Store the variables in a list and then access the wanted variable through linq:
object getValue (string name)
{
return variablesList.Where(v => v.Name == name).First();
}
Both are very simple but the second one (linq) seems more compelling because it uses linq and also because in the first method the same name is stored in two different places which is redundant.
What is the best method with respect to best practices and performance?
Thanks
Using a dictionary is way faster than using a list, at least in any case when it matters.
The performance of a dictionary lookup is O(1), while a list search is O(n). That means that it takes the same time to find the item in the dictionary with few items as with many items, but finding them in the list takes longer the more items that you have.
For very small sets of variables the list may be slightly faster, but then they are both so fast that it doesn't matter. With many items the dictionary clearly outperforms the list.
The dictionary uses a bit more memory, but not so much. Remember that it will only store the reference to the name, it's not another copy of the string.
You should definitely use a Dictionary in this case. If you use a List and want to do a lookup, in the worst case the program has to loop over the entire list to find the right object. For a Dictionary, this is always a constant time, irrespective of its size.
By the way, 'uses LINQ' is not a good reason to prefer one method over the other.
What you're trying to do is exactly what dictionaries were designed for.
Technically, any dictionary that uses an object property as a key to that object will be "redundant" as you describe, but because string is a reference type, it's not like you'll be using up a huge amount of memory to store the "redundant" key.
At the cost of a few extra bytes, you get a huge performance increase. The thing that makes dictionaries so cool is that they're hash tables, so they'll always look up an element from a key quickly, no matter how big they are. But if you use a list and try to iterate over it with LINQ, you might have 10,000 items in the list and the one you're looking for is at the end, and it will take approximately 10,000 times longer than looking it up with a Dictionary. (For a more formal look at the math involved, try Googling "Big O notation" and "time complexity". It's a very useful bit of theory to know about when developing software!)

What is the correct way of using a Dictionary in C#?

I have (lots of) objects Foo with an unique ID and want to store these in a Dictionary. The dictionary key in C# can be any primitive type or object. I could use the integer foo1.ID as key but also the object foo1.
Which is the correct way of implementing that and is there a difference in performance using either the ID (an integer) or the object as key?
NB. The values in the dictionary are other (type of) of objects.
How do you intend to search the dictionary? If you intend to search for items within the dictionary based purely on ID, then use that as the key. OTOH, if you're going to have an instance of a Foo, then make that the key.
Re: your edit - now we know that the Foo is either "the key" or "the object that provides the key value by accessing a property", then it seems simple to say, use a Dictionary<Foo,OtherClass> - assuming you've set up equality comparisons on Foo objects appropriately - why force every instance of lookup to know to extract a specific property from the Foo objects?
It depends on your use case. Assuming you want to look up objects given their key value you of course want the id to be the key. That you are asking this question makes me think maybe you don't want a dictionary at all - if you just need to keep a collection of items use a List<T> instead - dictionaries are for mapping a key (e.g. an id) to a value (e.g. a custom object).
Whatever you use as a key has to be able to be compared. For primitive types, equality is defined generally as you would expect. For objects, you would be testing reference equality unless you define another way to compare the objects, which you can do by passing the appropriate type of IComparer in the Dictionary constructor.
In your case, however, keying to the int is likely to be simplest. You would gain no real benefit from using the object as its own key. You can create the dictionary simply by taking your collection of Foo objects and doing something like:
IDictionary<int, Foo> fooDictionary = fooCollection.ToDictionary(f => f.ID);
Searching the dictionary will be more efficient than simply searching the collection for the given ID each time in most cases.
Dictionaries are Key Value Pairs. Each Key should be Unique. The Compiler has to make sure the Keys are unique. By Giving the Key as an object instead of an integer, You are probably doing an overkill. The compiler has compare to check the whole object in the Key to make sure it is unique. So i would go for Integer Key if that help you to identify your record uniquely.
Use the ID - if you already have the object, there's no point in looking it up, too.

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

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

Get first key from Dictionary<string, string>

I'm using a System.Collections.Generic.Dictionary<string, string>.
I want to return the first key from this dictionary. I tried dic.Keys[0] but the only thing I have on the Keys property (which is a KeyCollection object) is an enumerator.
Do I have to enumerate through all the keys to get the first one?
Assuming you're using .NET 3.5:
dic.Keys.First();
Note that there's no guaranteed order in which key/value pairs will be iterated over in a dictionary. You may well find that in lots of cases you get out the first key that you put into the dictionaries - but you absolutely must not rely on that. As Skirwan says, there isn't really a notion of "first". Essentially the above will give you "a key from the dictionary" - that's about all that's guaranteed.
(If you don't know whether the dictionary is empty or not, you could use FirstOrDefault.)
The idea of 'first' doesn't really apply to a dictionary, as there's no ordering on the entries; any insert or remove is allowed to radically change the order of the keys.
Firstly, no, you do not have to enumerate all of the entries — just enumerate the first item:
IEnumerator enumerator = dictionary.Keys.GetEnumerator();
enumerator.MoveNext();
object first = enumerator.Current;
Ideally one would check that the MoveNext() actually succeeded (it returns a bool) otherwise the call to Current may throw.
Please also note that the order of a dicitonary is not specified. This means that the 'first' item may in fact be any key, may be different on subsequent calls (though in practice will not) and will certainly change as items are added and removed from the dictionary.
Seems a bit over the top, but how about
foreach (<Type> k in dic.Keys)
return k;
we can using linq technology
var key = dic.Take(1).Select(d => d.Key).First()
or we can use another search
var myList = dic.Take(1).Where(d => d.Key.Contains("Heaven")).ToList();

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