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

C# 基于密钥有效地配对列表中的对象,c#,arrays,sorting,C#,Arrays,Sorting,那么,就这么定了。 (我当前的用例是C#,但我也对一般的算法用例感兴趣) 我得到了两个对象数组(不幸的是,我无法修改创建这些数组的代码)。 每个对象(作为其一部分)都有一个.Name属性,一个字符串。 这些字符串对于每个对象都是唯一的,并且在另一个对象中有零个或一个匹配字符串。 我需要做的是基于该字符串高效地将这些对象配对到某种集合中,以允许我访问配对对象。字符串需要精确匹配才能被视为匹配,因此我不需要任何大写或不区分大小写的字符串,等等。 遗憾的是,这些列表没有排序。 列表本身可能有30-50

那么,就这么定了。 (我当前的用例是C#,但我也对一般的算法用例感兴趣) 我得到了两个对象数组(不幸的是,我无法修改创建这些数组的代码)。 每个对象(作为其一部分)都有一个.Name属性,一个字符串。 这些字符串对于每个对象都是唯一的,并且在另一个对象中有零个或一个匹配字符串。 我需要做的是基于该字符串高效地将这些对象配对到某种集合中,以允许我访问配对对象。字符串需要精确匹配才能被视为匹配,因此我不需要任何大写或不区分大小写的字符串,等等。 遗憾的是,这些列表没有排序。 列表本身可能有30-50个条目,但我需要在一行中的数千个数组对上重复该算法,因此效率很重要

因为我知道有0或1个匹配,而且我知道大多数匹配都是1个匹配,所以我觉得有一个比x*y更有效的算法(x中的Foreach项,y中的Foreach项,如果x=y,那么x和y是匹配的)

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

保留未排序的列表,只做x*y,但一旦我找到了,就从列表中删除项目,这样我就不会检查已经找到的项目, 或: 将两者转换为字典,然后对每个字典进行索引查找(array2[currentArray1Item]) 或: 我自己对列表进行排序(Array.Sort()),然后对数组进行排序,我可能会做一些聪明的事情,比如跳转到B中的索引,在那里我希望找到它(在A中的任何位置),然后根据字符串上下移动,直到我找到它或传递它应该在的位置

一旦完成了,我需要弄清楚如何存储它,我想我可以创建一个定制的ObjectPair类,它只保存对象a和B。这里不需要做任何花哨的事情,因为我只需要在对象对上进行ForEach

因此,问题是: 上述算法是否是实现这一点的最快方法(如果不是,是什么?),是否存在一些现有的C#结构可以方便地保存找到的对


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

使用
数组对第二个数组进行排序。排序
方法,然后使用
二进制搜索算法匹配第二个
数组中的对象


通常,对于30-50个项目,这将比暴力x*y略快。

使用
数组对第二个数组进行排序。排序
方法,然后使用
二进制搜索算法匹配第二个
数组中的对象


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

我的问题是:如果特殊处理要求我们对两个输入数组进行排序,我们能从中获得多少效率?根据的文档,它平均为
O(n log n)
,在最坏的情况下为
O(n^2)
(快速排序)。一旦我们对两个数组进行了排序,我们就会有另一个
O(n)
工作量,因为我们必须循环第一个数组

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

您可以考虑使用LINQ联接,它只对内部数组迭代一次()。这与嵌套的

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
}

这非常清楚地说明了您对数据所做的操作,并为您提供了表示每对数据的匿名类型(因此您不必发明配对)。如果您最终选择了另一条路线,我会对它与这种方法的比较感兴趣。

我的问题是:如果特殊处理要求我们对两个输入阵列进行排序,我们能从中获得多少效率?根据的文档,它平均为
O(n log n)
,在最坏的情况下为
O(n^2)
(快速排序)。一旦我们对两个数组进行了排序,我们就会有另一个
O(n)
工作量,因为我们必须循环第一个数组

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

您可以考虑使用LINQ联接,它只对内部数组迭代一次()。这与嵌套的

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
}

这非常清楚地说明了您对数据所做的操作,并为您提供了表示每对数据的匿名类型(因此您不必发明配对)。如果你最终选择了另一种方法,我会对它与这种方法的比较感兴趣。

哦,数组本身有一种排序,我想我必须转换成列表。另一种方法是