问题
I had a dictionary to store pattern images for OCR purposes. I grabbed these bitmaps from dictionary and compared to ones that I cropped from image, if they matched => grabbed the key (OCR part is done).
The problem arises here. One Key should be represented by several different bitmaps (i.e. values). How do you add multiple bitmaps to the dictionary, to represent the same key?
that's how I used dictionary:
Dictionary<string, Bitmap> lookup = new Dictionary<string, Bitmap>();
lookup.Add("A", new Bitmap(@"C:\08\letters\1\a1.bmp", true));
lookup.Add("A", new Bitmap(@"C:\08\letters\1\a2.bmp", true)); // Error will be here, because key A already exists for one Bitmap value.
lookup.Add("a", new Bitmap(@"C:\08\letters\1\aa1.bmp", true));
lookup.Add("B", new Bitmap(@"C:\08\letters\1\b1.bmp", true));
Now, to grab images and value I did following:
var target = lookup.ToList();
bitmap b1 = target[j].Value; //grab value
//if value = cropped bitmap => proceed
string key = target[j].Key; //grab key
How will this process change according to your solution?
P.s. I have heard of "System.Linq.Lookup(Of TKey, TElement)", but never used it before. Will this "lookup" help me solve my problem or is it a completely different tool? google doesn't know much about it either, so an example would be welcomed
please note, that I load dictionary only once, at program start, so it doesn't matter how fast adding is. Lookup, on the other side is what bothers me the most. I have 120 elements in two of my dictionaries, and according to this article http://www.dotnetperls.com/dictionary-time - Lookup in the List is much more slower, than in dictionary..
anyway I'll be doing some measures to test out how List solution that was suggested below - compares to Dictionary solution which I have right now and tell the results later, probably this evening.
回答1:
Lookup. It is basically a dictionary of Key to list of Values, instead of key to value.
lookup.Add("a", "123"); // creates 'a' key and adds '123' to it
lookup.Add("a", "456"); // adds '456' to existing 'a' key
lookup.Add("b", "000"); // creates 'b' key and adds '000' to it
回答2:
You can not add item into a dictionary
with the same key. I think you are using the wrong data structure. I thing you might have to look into using a list<>
instead. Like this:
var lookup=new List<KeyValuePair<string,Bitmap>>();
lookup.Add(new KeyValuePair<string,Bitmap>("A", new Bitmap(@"C:\08\letters\1\a1.bmp", true)));
lookup.Add(new KeyValuePair<string,Bitmap>("A", new Bitmap(@"C:\08\letters\1\a2.bmp", true)));
lookup.Add(new KeyValuePair<string,Bitmap>("a", new Bitmap(@"C:\08\letters\1\aa1.bmp", true)));
lookup.Add(new KeyValuePair<string,Bitmap>("B", new Bitmap(@"C:\08\letters\1\b1.bmp", true)));
The you can do this instead. Without doing ToList()
:
bitmap b1 = target[j].Value; //grab value
string key = target[j].Key; //grab key
Edit
But if you are doing a ToList()
on a Dictionary
then you are missing the point of having a Dictionary
in the first place. Because then you are accessing the Dictionary
anyway the list
way. I can also see a problem doing a ToList()
on a Dictionary
because the sorting in a Dictionary
is not as you insert them, it is by hash. That means that you can not be sure that Index 1 is index 1. You also have to take in considerations that the operation add
on a Dictionary
is not as effective as the add
on a List
. The god things with a Dictionary is that the lookup is fast. But that are you not using with your current solution.
So there is two ways what i can see. The one above or make sure that the keys are unique and get it by the lookup in the Dictionary
. Like this:
Dictionary<string, Bitmap> lookup = new Dictionary<string, Bitmap>();
lookup.Add("A", new Bitmap(@"C:\08\letters\1\a1.bmp", true));
lookup.Add("B", new Bitmap(@"C:\08\letters\1\a2.bmp", true));
lookup.Add("C", new Bitmap(@"C:\08\letters\1\aa1.bmp", true));
lookup.Add("D", new Bitmap(@"C:\08\letters\1\b1.bmp", true));
Then you can get the Bitmap
like this:
Bitmap bm;
if(lookup.TryGetValue("A",out bm))
{
//Do something
}
Or if you know that the key is present in the Dictionary
then you can do like this:
Bitmap bm;
bm= lookup["A"];
回答3:
First, it's different to have 'multiple bmp-s' to 'represent the key' - or have 'one key' associated (mapped) into multiple 'values' - which is what Yorye suggested rightly.
So, if you want more values attached to a single key - then you can use something like Dictionary<TKey, IList<TValue>>
- where TKey and TValue are types you need.
But that doesnt' solve indexing and querying of the data.
That assumes that your 'key' is just 'A' in your case - which is not clear what it is.
So in that case you're using the 'dictionary' for something that it shouldn't be used. Dictionary is a hashing structure (basically indexes all its entries into buckets etc.) which servers the purpose of speeding up the querying process, locating the 'right' value.
As I see in your case the 'key' is/are the 'set of bitmaps' which sort of present a 'signature' of the OCR-ed image, if I"m right? I'm not much into the OCR but I'm guessing here.
That complicates things a bit, you'd need to create a 'composite' key of a sort.
The 'key' and not the 'value' (or value list) would be the bitmaps (providing they can be made to be comparable and equal or non-equal, also there's a problem of how you compare multiple values to multiple values etc.).
If that's the case usually (but for simpler cases than yours), you'd create a custom class and make that class have a GetHashCode() Equals override (or IEqualityComparer) etc. so that it can be used as a key in dictionaries. And then you use that as a key.
Again, in your case I think that's a bit of a stretch (in a sense that it's not easy to implement).
Basically you need to think about 'querying' the data, not much as storing. What are the real 'keys' for your system. If it's a bitmap, that's always the same (or if not how you compare to signature bmps) then you might save some bmp hashcode instead and use that as a key - and compare that, instead of bmps.
i.e. you need to think about things like that - and then the solution will usually be obvious, what you need to use.
I would not recommend a list, as that's a poor-men's choice - unless you might have only a couple so it's easy to go through it by hand, somehow I dont' think that's the case in your case.
If you need some way of 'indexing' by some key or keys - then it's usually the dictionary (or dictionary is involved in some way or part) - but you can have many 'dictionaries' - or combinations. Also you can have 'many types of keys' and values etc.
You'd need to give us some data for that.
hope this helps
EDIT: And lastly - getting the right 'hash-code' is also not a simple thing to do - as with your custom structure, comnparing, that's something you need to work out yourself - so that boils down to what's your key - and what represents the 'key' (as in which property, value best describes it and makes it unique, hard thing to do for an image/bmp?), the distribution of hash values etc.
来源:https://stackoverflow.com/questions/9963706/adding-multiple-bitmap-values-for-one-key-in-dictionary-with-c-sharp