I am working with C# for a Hexagon shaped grid with bound checks and wrapping etc. The map in the library is a dictionary Dictionary<TileCoord,int> tileIndexByPosition. I also have the required function to obtain CornerCoord for each tile.
I would like to create a dictionary Dictionary<CornerCoord,int> cornerIndexByPosition whose values depend on tileIndexByPosition. Whenever tileIndexByPosition changes its elements creating a new dictionary for corners seems quite inefficient.
The idea I have is to use the Lazy evaluation of LINQ to strongly couple the two dictionary. Would like any advice on how to approach this problem.
EDIT: I use these dictionary to check if a TileCoord or CornerCoord is part of the map by using the ContainsKey.
I would use a KeyValuePair like this
KeyValuePair<Dictionary<TileCoord,int>,Dictionary<CornerCoord,int>> kvp;
If you change the Key ( tileIndexByPosition ) you also can change the Dictonary Value of the KeyValuePair Value that depends on the KeyValuePair Key.
This is like you said you want. But I think you want something like this:
Dictonary<KeyValuePair<TileCoord,int>,KeyValuePair<CornerCoord,int>> dic;
I hope this helps.
Kind regards
Related
Normally, I use a dictionary like a list, but with a key of a different type. I like the ability to quickly access individual items in the dictionary without having to loop through it until I find the item with the right property (because the property I'm looking for is in the Key).
But there is another possible use of a dictionary. I could just use the Key to store property A and the Value to store property B without ever using the dictionary's special functionality. For example, I could store a list of persons just by storing the forename in the key and the family name in the value (let's assume, for the sake of simplicity, that there won't ever be two people with the same forename, because I just couldn't come up with an better example). I would only use that dictionary to loop through it in a foreach loop and add items to it (no removing, sorting or accessing individual items). There would actually be no difference to using a List<KeyValuePair<string, string>> from using a Dictionary<string, string> (at least not in the example that I gave - I know that I could e. g. store multiple items wiht the same key in the list).
So, to sum it up, what should I do when I don't need to use the special functionalities a dictionary provides and just use it to store something that has exactly two properties:
use a Dictionary<,>
use a List<KeyValuePair<,>
use a List<MyType> with MyType being a custom class that contains the two properties and a constructor.
Don't use dictionaries for that.
If you don't want to create a class for this purpose, use something like List<Tuple<T1,T2>>. But keep in mind a custom class will be both more readable and more flexible.
Here's the reason: it will be much more easy to read your code if you use proper data structures. Using a dictionary will only confuse the reader, and you'll have problems the day a duplicate key shows up.
If someone reads your code and sees a Dictionary being used, he will assume you really mean to use a map-like structure. Your code should be clear and your intent should be obvious when reading it.
If you're concerned with performance you should probably store the data in a List. A Dictionary has lots of internal overhead. Both memory as well as CPU.
If you're just concerned with readability, chose the data structure that best captures your intent. If you are storing key-value pairs (for example, custom fields in a bug tracker issue) then use a Dictionary. If you are just storing items without them having some kind of logical key, use a List.
It takes little work to create a custom class to use as an item in a List. Using a Dictionary just because it gives you a Key property for each item is a misuse of that data structure. It is easy to create a custom class that also has a Key property.
Use List<MyType> where MyType includes all the values.
The problem with the dictionary approach is that it's not flexible. If you later decide to add middle names, you'll need to redesign your whole data structure, rather than just adding another field to MyType.
I'm planning to create a class representing a html table, problem is that it must be able to contain 3+ dimensions, one dimension will be the width of course, the rest will be along the length like this:
foo1:bar1
foo1:bar2
foo2:bar1
foo2:bar2
etc.
Now I'm contemplating how to represent this in my class, my idea is to use a multi-level dictionary, i.e. one that can be indexed like this: myDict[fooKey][barKey][...], is that a good idea? Is it possible? How?
Can I let the user of the class give it any Dictionary along with an int depth and then cast to dictionary when using the class internally?
edit: Seems like I was a bit unclear, there is a practical depth limit obviously, but I'd prefer to code it for any depth, the depth should be given by the user of the class.
you can use a Dictionary with type of Key Dictionary...
so you can say:
Dictionary<string, Dictionary < string, string>> x;
and use it as mentioned of you..
x["asdf"]["asdf"] = "asdf";
Basically I have a Dictionary<Guid, Movie> Movies collection and search for movies using Guid, which is basically movie.Guid. It works great, but I also want to be able to search the same dictionary using movie.Name without looping through each element.
Is this possible or do I have to create another Dictionary<K, V> for this?
Just have two Dictionaries, one of them having the guid as its key and the other with the name as its key.
If you don't want to look at every element, you need to index it the other direction. This means another Dictionary to get O(1).
You can iterate across the variables but then you arnt getting the constant-time searching value in a dictionary (because of the way that the keys are hashed.) The answer above regarding using two dictionarys to hash references to your object may be a good solution if you dont have too many objects to reference.
You could search with the Values property:
dictionary.Values.Where(movie => movie.Name == "Some Name")
You'll lose the efficiency of a key based look up, but it will still work.
Since dictionaries are for one-way mapping you can't get keys from values.
You'll need two dictionaries.
There is also a suggestion:
You can use a custom hash function for keys instead of GUIDs and store Movie Names hash as keys. Then you can actually perform two way search in your dictionary.
Rather than using two dictionaries, you'd be much better off using one container class that has two dictionaries inside it.
Some guy named Jon came up with a partial solution to this (which you could easily build upon), leaving his code here: Getting key of value of a generic Dictionary?
You can't use that dictionary to do that search with anything like the same efficiency. But you can easily just run a LINQ query against your dictionary's Values property, which is just collection of the Movie values.
var moviesIWant = From m in movieLookup.Values
Where m.Name == "Star Wars"
Select m
Some thoughts:
When you find your answer though, you would not have the guids, unless they were also a property of movie.
For a small dictionary, this is just fine. For large and repeated searches, you should consider the creation of other dictionaries keyed on the other values you wish to search on. Only in this way would you achieve the speed of a guid lookup comparable to your original dictionary.
You could create another dictionary keyed by Name. Once you've done this, you could search this dictionary by it's key and it would have the same super-efficiency of your original dictionary, even for a very large dictionary.
var moviesByName = movieLookup.Values.ToDictionary(m => m.Name, m => m)
No I don't believe it is possible. You'll have to use another dictionary.
If you are going to want to search on more movie attributes you may be better off moving the data down to a database and use that for querying. That is what databases are good for after all.
I have a dictionary structure, with multiple key value pairs inside.
myDict.Add(key1, value1);
myDict.Add(key2, value2);
myDict.Add(key3, value3);
My dictionary is used as a data source for some control. In the control's dropdown I see the items are like this:
key1
key2
key3
The order looks identical to my dictionary.
I know Dictionary is not like arrayList - you can get the index or so.
I cannot use sortedDictionary.
Now I need to add one more key value pair to this dictionary at some point of my program and I hope it has the same effect as I do this:
myDict.Add(newKey, newValue);
myDict.Add(key1, value1);
myDict.Add(key2, value2);
myDict.Add(key3, value3);
If I do this, I know newKey will display in my control as first element.
I have an idea to create a tempDict, put each pair in myDict to tempDict, then clear myDict, then add pairs back like this:
myDict.Add(newKey, newValue);
myDict.Add(key1, value1);
myDict.Add(key2, value2);
myDict.Add(key3, value3);
Is there better way than this?
Thanks!
Dictionary<K,V> does not have an ordering. Any perceived order maintenance is by chance (and an artifact of a particular implementation including, but not limited to, bucket selection order and count).
These are the approaches (just using the Base Class Libraries BCL) I know about:
Lookup<K,V>
.NET4, immutable, can map keys to multiple values (watch for duplicates during building)
OrderedDictionary
Old, non-generic, expected Dictionary performance bounds (other two approaches are O(n) for "get(key)/set(key)")
List<KeyValuePair<K,V>>
.NET2/3 okay, mutable, more legwork, can map keys to multiple values (watch for duplicates in inserts)
Happy coding.
Creating a hash data-structure that maintains insertion order is actually only a slight modification of a standard hash implementation (Ruby hashes now maintain insertion order); however, this was not done in .NET nor, more importantly, is it part of the Dictionary/IDictionary contract.
You cannot do that with the Dictionary class. It is working in your example because of a quirk in the way the data structure is implemented. The data structure actually stores the entries in temporal order in one array and then uses another array to index into the entry array. Enumerations are based on the entry array. That is why it appears to be ordered in your case. But, if you apply a series of removal and insertion operations you will notice this ordering gets perturbed.
Use KeyCollection instead. It provides O(1) retrieval by both key and index and preserves temporal ordering.
From the MSDN page on Dictionary(TKey, TValue):
For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair<(Of <(TKey, TValue>)>) structure representing a value and its key. The order in which the items are returned is undefined.
I'm assuming you can't use SortedDictionary because the control depends on your data source being a Dictionary. If the control expects both the Dictionary type and sorted data, the control needs to be modified, because those two criteria contradict each other. You must use a different datatype if you need sorting/ordering functionality. Depending on undefined behavior is asking for trouble.
Don't use a dictionary - there is no guarantee the order of the keys won't change when you add further elements. Instead, define a class Pair for your Key-Value-Pairs (look here What is C# analog of C++ std::pair? for an example) and use a List<Pair> for your datasource. The List has an Insert operation you can use to insert new elements anywhere into your list.
Dictionary Should not be used to sort objects, it should rather be used to look up objects. i would suggest something else if you want to have it sort the objects too.
If you expand the Dictionary, there are no rule that would stop it from mixing up your List.
I have Dictionary<long, Location> PostalCodes .
While i m adding new elements to this Dictionary I want to make a lookup to this dictionary and if the Location.PostalCode is not in this dictionary, I want to insert it. Otherwise I want to skip it. So , need to know if the PostalCode is already in the Collection. Cant use it as the key.
How to do this?
Thanks.
It sounds like you need another dictionary which does use it as the key - basically a bidirectional map. At least, that's if you want it to perform well. You could just look through every value in the map, but that would be an O(n) operation.
(Alternatively, if you're doing this once, just create a HashSet<Location> for all the locations you're using. You don't actually need the long, by the sounds of it for the purpose of the reverse lookup.)
You can try:
if(PostalCodes.Values.All(l=>l.PostalCode != location.PostalCode))
{
PostalCodes.Add(key /*what is it*/, location);
}
But this might get slow with large amount of data.