使用C#在字典中为一个键添加多个位图值

4
我有一个用于OCR目的的字典来存储模式图像。我从字典中获取这些位图并将它们与我从图像中裁剪出来的位图进行比较,如果它们匹配,则抓取键(OCR部分已完成)。
问题在于这里出现了。一个键应该由多个不同的位图(即值)表示。如何向字典中添加多个位图以表示相同的键?
下面是我使用字典的方法:
    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));

现在,为了获取图片和值,我按照以下步骤进行:
var target = lookup.ToList();
bitmap b1 = target[j].Value; //grab value
//if value = cropped bitmap => proceed
string key = target[j].Key; //grab key

根据您的解决方案,这个过程将如何改变?

P.s. 我听说过“System.Linq.Lookup(Of TKey, TElement)”,但以前从未使用过。这个“lookup”能帮我解决我的问题吗,还是它是一个完全不同的工具?谷歌对此也不了解,所以欢迎提供示例。

请注意,我只在程序启动时加载字典一次,因此添加速度有多快并不重要。另一方面,Lookup是我最担心的问题。 我有两个字典中的120个元素,根据这篇文章http://www.dotnetperls.com/dictionary-time - 在列表中进行查找比在字典中慢得多..

无论如何,我将采取一些措施来测试下面建议的列表解决方案与我现在拥有的字典解决方案相比较,并稍后告诉结果,可能是今晚。

3个回答

2

Lookup是一个基本上是将Key映射到值列表而不是单个值的字典。

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

1
你如何声明lookup?我尝试了“Lookup<string, Bitmap> lookup= new Lookup<string, Bitmap>();”,但结果是“The type 'System.Linq.Lookup<TKey,TElement>' has no constructors defined”。 - Alex
它应该可以在至少 .Net4 上工作,但你也可以按照这里所示的方式间接地创建它:http://msdn.microsoft.com/en-us/library/bb460184(v=vs.90).aspx - SimpleVar

0
首先,有“多个bmp-s”来“表示密钥”与将“一个密钥”关联(映射)到多个“值”是不同的,这正是Yorye正确建议的。因此,如果您想要将更多的值附加到单个键上,则可以使用类似于Dictionary<TKey, IList<TValue>>的东西,其中TKey和TValue是您需要的类型。但是,这并不能解决数据的索引和查询问题。这假设您的“键”只是“A”,在您的情况下并不清楚它是什么。因此,在这种情况下,您正在使用“字典”用于不应该使用的东西。字典是一种哈希结构(基本上将其所有条目索引到桶等中),它的作用是加快查询过程,定位“正确”的值。正如我在您的情况中所看到的,“键”是/是OCR图像的“一组位图”,这些位图在某种程度上呈现了OCR图像的“签名”,如果我没错的话?我对OCR不太熟悉,但我在这里猜测。这使事情变得有点复杂,您需要创建一种“复合”键。而不是“值”(或值列表),位图将是“键”(前提是它们可以被制作成可比较和相等或不相等的状态,还存在如何将多个值与多个值进行比较等问题)。如果是这种情况,通常(但对于比您简单的情况),您会创建一个自定义类,并使该类具有GetHashCode() Equals覆盖(或IEqualityComparer)等,以便可以在字典中使用它作为键。然后您将其用作键。再次,在您的情况下,我认为这有点牵强(在某种意义上,它不容易实现)。基本上,您需要考虑“查询”数据,而不是存储数据。您的系统的真正“键”是什么。如果它是位图,则始终是相同的(或者如果不是,则如何与签名bmp进行比较),那么您可能会保存一些bmp哈希代码,然后将其用作键-并进行比较,而不是bmps。也就是说,您需要考虑诸如此类的事情,然后解决方案通常会很明显,您需要使用什么。我不建议使用列表,因为那是穷人的选择-除非您只有几个,这样很容易手动处理,但我不认为这是您的情况。如果您需要按某些键或键进行“索引”,则通常是字典(或字典以某种方式或部分参与其中)-但您可以拥有许多“字典”-或组合。您需要为我们提供一些数据。希望这可以帮助您。最后,获取正确的“哈希码”也不是一件简单的事情-因为对于您的自定义结构,比较,这是您需要自己解决的问题-因此,这归结为什么是您的键-以及什么代表“键”(例如哪个属性,值最能描述它并使其独特,对于图像/ bmp来说是很难做到的?),哈希值的分布等。

0
您不能使用相同的键将项添加到字典中。我认为您正在使用错误的数据结构。我想您可能需要考虑改用一个 list<>。像这样:
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)));

你可以这样做,而不需要使用ToList()

bitmap b1 = target[j].Value; //grab value
string key = target[j].Key; //grab key

编辑

但是,如果您在Dictionary上执行ToList(),那么您就错过了首先拥有Dictionary的意义。因为这样,您无论如何都会以list的方式访问Dictionary。我还可以看到在Dictionary上执行ToList()存在问题,因为Dictionary中的排序不是按照插入顺序进行的,而是按照哈希值进行的。这意味着您不能确定索引1是索引1。您还必须考虑到Dictionary上的add操作不像List上的add操作那样有效。使用Dictionary的好处是查找速度快。但是,您当前的解决方案并没有使用它。

所以我看到有两种方法。上面的一种或确保键是唯一的,并通过在Dictionary中查找来获取它。就像这样:

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));

然后你可以像这样获取Bitmap

Bitmap bm;
if(lookup.TryGetValue("A",out bm))
{
    //Do something
}

或者如果您知道键存在于字典中,那么可以这样做:

Bitmap bm;
bm= lookup["A"];

好的,我有几个问题:相比于字典,这个“列表方法”慢/快多少?根据这篇文章“http://www.dotnetperls.com/dictionary-time”,仅有12个元素的列表比字典慢两倍。我正在一个字典中存储120个元素,所以有些事情告诉我,列表可能不是最好的解决方案。 - Alex
更新了答案。请查看。 - Arion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接