By creating a Dictionary<int,int> or List<KeyValuePair<int,int>> I can create a list of related ids.
By calling collection[key] I can return the corresponding value stored against it.
I also want to be able to return the key by passing in a value - which I know is possible using some LINQ, however it doesn't seem very efficient.
In my case along with each key being unique, each value is too. Does this fact make it possible to use another approach which will provide better performance?
It sounds like you need a bi-directional dictionary. There are no framework classes that support this, but you can implement your own:
Bidirectional 1 to 1 Dictionary in C#
You could encapsulate two dictionaries, one with your "keys" storing your values and the other keyed with your "values" storing your keys.
Then manage access to them through a few methods. Fast and the added memory overhead shouldn't make a huge difference.
Edit: just noticed this is essentially the same as the previous answer :-/
Related
Is it a good practice to use your domain objects as keys in a Dictionary ?
I have a scenario where I populate my domain object using NHibernate.
For performing business logic I need to look-up Dictionary. I can make use of
Either
IDictionary<int, ValueFortheObject>
or
Dictionary<DomainObject, ValueFortheObject>
The second options seems better to me as
I can write easier test cases and can use real domain objects in test cases as well rather than using Mock<DomainObject> (if I go with the first option) since setter on the Id is private on ALL domain objects.
The code is more readable as Dictionary<Hobbit,List<Adventures>> is more readable to me than Dictionary<int,List<Adventures>> with comments suggesting int is the hobbitId especially when passing as parameters
My questions are :
What are advantages of using the first option over the second (which I might be blindly missing) ?
Will be any performance issues using the second approach?
Update 01:
My domain models implement those and they DO NOT get mutated while performing the operations.
Will there be issues with performance using them as keys ? or am I completely missing the point here and performance / memory are not related to what keys are being used?
Update 02:
My question is
Will there be any issues with performance or memory if I use Objects as keys instead of primitive types and WHY / HOW ?
The biggest issue you will run in to is you must not mutate your key object while it is performing it's roll as a key.
When i say "mutate" I mean your key object must implement Equals and GetHashCode to be used as a key for a dictionary. Anything you do to the object while it is being used as a key must not change the value of GetHashCode nor cause Equals to evaluate to true with any other key in the collection.
#ScottChamberlain gives you the overall issue, but your use cases could argue either way. Some questions you should ask yourself are: what does it mean for two business objects to be equal? Is this the same or different if they are being used as a key in a dictionary or if I'm comparing them elsewhere? If I change an object, should it's value as a key change or remain the same? If you use overrides for GetHashCode() and Equals(), what is the cost of computing those functions?
Generally I am in favor of using simple types for keys as there is a lot of room for misunderstanding with respect to object equality. You could always create a custom dictionary (wrapper around Dictionary<Key,Value>) with appropriate method if readability is your highest concern. You could then write the methods in terms of the objects, then use whatever (appropriate) property you want as the key internally.
I have a List<IAgStkObject>. Each IAgStkObject has a property called InstanceName. How can I search through my List to find if any of the contained IAgStkObject(s) have a particular InstanceName? In the past I would have used a foreach loop.. but this seems too slow.
WulfgarPro
If the only thing you have is a List (not ordered by InstanceName), there is no faster way (if you do similar tests often, you can preprocess the data and create e.g. a Dictionary indexed by the InstanceName).
The only way different from “the past” would be those useful extension methods allowing you to write just
return myList.Any(item => item.InstanceName == "Searched name");
If the list is sorted by the InstanceName, you can use binary search algorithm, otherwise: no.
You would have to use some more advanced data structure (like the sorted list or dictionary). I think dictionary would be the solution for this. It is very fast and easy to use.
But think: how many of the objects do you have? Are you sure looping through them is performance issue? If you have < 1000 of the objects, you absolutely don't have to worry (unless you want to do something in real time).
You can use Linq:
list.Any(o => o.InstanceName == "something")
But you cannot avoid looping through the list (in the Linq case it's done implicitly). If you want a performance gain, change your data structure. Maybe a dictionary (InstanceName -> IAgStkObject) is appropriate?
I have a dictionary data structure that must be passed around using WCF. To do that I created a member property with get and set methods. I can basicly achieve the same functionality, with this property being either a:
IDictionary<keyType, valueType>
or a
IList<KeyValuePair<keyType, valueType>>
I can see no strong reason for choosing one over the other. One mild reaons I could think of is:
IDictionary - People reading the code will think that IDictionary makes more sense, since the data structure is a dictionary, but in terms of what is passed through WCF they are all the same.
Can anyone think of a reason to choose IList? If there is none I'll just go with IDictionary.
Design your interfaces based on use, not on implementation.
If the consumer of a class needs to iterate through the entire set, use IEnumerable. If they should be able to modify the result, and need index-based access, return IList. If they want specific items, and there is a single useful key value, return IDictionary.
Write your internal code this way, too :)
It depends on your consumers. I would cater for the most likely use case and make their API as simple as possible. Edge cases can always iterate the dictionary via the Values collection.
Don't make them think about it. If the the term dictionary is what they'd think about as the result of the operation and then the type with name is a very useful thing to use.
If the collection of keyValuePairs expects unique key, you can use dictionary.
If the same key can appear in more than one keyValuePair, use Ilist/ ienumerable.
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.
I'm using a HashSet<T> to store a collection of objects. These objects already have a unique ID of System.Guid, so I'd rather the HashSet<> just use that existing ID rather then trying to figure out itself how to hash the object. How do I override the build in hashing and force my program to use the build in ID value as the hash value?
Also say I know the Guid of an object in my HashSet<>, is there a way to get an object from a HashSet<T> based on this Guid alone? Or should I use a dictionary instead.
A HashSet<> is not based a key/value pair, and provides no "by key" access - it is just a set of unique values, using the hash to check containment very quickly.
To use a key/value pair (to fetch out by Guid later) the simplest option would be a Dictionary<Guid,SomeType>. The existing hash-code on Guid should be fine (although if you needed (you don't here) you can provide an IEqualityComparer<T> to use for hashing.
Override the GetHashCode() method for your object.
Of course, there's a slight wrinkle here... GUIDs are larger than int32s, which .NET uses for hashcodes.
Why do you need to override this? seems like perhaps a premature optimization.
Yeah, just use a dictionary. Once you develop your application, go through a performance tuning phase where you measure the performance of all your code. If and only If this hashing function shows as being your largest drain should you consider a more performant data structure (if there is one anyways) :-)
Try looking into System.KeyedCollection. It allows you to embed the knowledge of the key field into your collection implementation.