基于密钥有效地配对列表中的对象

时间:2012-06-18 16:04:59

标签: c# arrays sorting

所以,这是交易。 (我目前的用例是C#,但我也对一般的算法案例感兴趣) 我得到了两个对象数组(不幸的是,我没有改变创建这些数组的代码)。 每个对象都有(作为其一部分).Name属性,一个字符串。 这些字符串对于每个对象是唯一的,并且在另一个对象中它们具有零个或一个匹配的字符串 我需要做的是将基于该字符串的这些对象有效地配对到某种允许我访问配对对象的集合中。字符串需要完全匹配才能被认为是匹配,因此我不需要任何Upper或CaseInsensitive等。 可悲的是,这些列表没有排序。 列表本身可能是30-50项,但我需要连续重复数千个这些阵列对的算法,因此效率很重要。

因为我知道有0或1个匹配,并且我知道它们中的大多数将是1个匹配,我觉得有一个比x * y更有效的算法(x中的Foreach项目,y中的foreach项目,如果x = y然后x和y匹配)

我认为最有可能的选择是:

保留未排序的列表,只做x * y,但是一旦找到它就从列表中删除项目,所以我不检查已找到的项目, 要么: 将两者都转换为Dictionaries,然后对每个字典进行索引查找(array2 [currentArray1Item]) 要么: 自己排序列表(Array.Sort()),然后排序数组我可以做一些聪明的事情,比如跳转到B中我希望找到它的索引(无论它在A中的哪个位置)然后向上移动或者基于字符串向下直到我找到它或通过应该去的地方。

然后,一旦完成,我需要弄清楚如何存储它,我想我可以创建一个自定义ObjectPair类,只保存对象A和B.不需要做任何花哨的事情,因为我只是去ForEach在对上。

所以问题是: 以上任何一种算法都是最快的方法吗(如果没有,是什么?)并且是否有一些现有的C#结构可以方便地保存找到的对?

编辑: Array.Sort()是一个存在的方法,因此我不需要将数组转换为List进行排序。很高兴知道。更新如上。

2 个答案:

答案 0 :(得分:3)

我的问题是:如果要求我们对两个输入数组进行排序,我们从特殊处理中获得多少效率?根据{{​​3}}的文档,平均为O(n log n),最差情况为O(n ^ 2)(quicksort)。一旦我们对这两个数组进行了排序,我们就会有另外O(n)的工作量,因为我们必须遍历第一个数组。

我认为这意味着总体工作量可能实际增加,因为排序所需的迭代次数,然后进行处理。如果您可以在开始时保证排序数组,那当然会是一个不同的故事,但正如您所说,您不能。 (我还应该注意,您需要创建一个自定义IComparer<T>实现以传递给Array.Sort,以便它知道使用.Name属性。这不是运行时工作,但它仍然有效: - )

您可以考虑使用LINQ连接,它只迭代内部数组一次(Array.Sort)。这与嵌套的foreach语句相反,后者将为外部数组的每个元素迭代内部数组。它与一般情况下的效率相同,并没有引入您建议的特殊处理的复杂性。

以下是一个示例实现:

var pairs =
    from item1 in array1
    join item2 in array2 on item1.Name equals item2.Name
    select new { item1, item2 };

foreach(var pair in pairs)
{
    // Use the pair somehow
}

非常清楚地说明了您在处理数据时所做的事情,并且还提供了代表每对的匿名类型(因此您不必发明配对)。如果你最终走的是另一条路线,我会对它与这种方法的比较感兴趣。

答案 1 :(得分:1)

使用Array.Sort方法对第二个数组进行排序,然后使用Array匹配第二个Binary Search Algorithm中的对象。

一般来说,对于30-50个项目,这比蛮力x * y快一点。