将每个元素与列表中的其他元素进行比较

Posted

技术标签:

【中文标题】将每个元素与列表中的其他元素进行比较【英文标题】:Comparing each element with each other element in a list 【发布时间】:2013-06-06 13:47:20 【问题描述】:

编写将遍历列表中每个 2 元素组合的控制结构的最佳方法是什么?

例子:

0,1,2

我想让一段代码运行 3 次,每次运行一次:

0,1
1,2
0,2

我尝试了以下

foreach (int i in input)

    foreach (int j in input.Where(o => o != i))
    
        //Execute code
    

但是,当列表包含两个相同的元素时,这将不起作用。与

0,2,0

我仍然想比较元素 00。该值无关紧要。

【问题讨论】:

你对每一对都在做什么?您的解决方案和 Jon 的解决方案都是 O(n squared)。根据您正在做的事情,可能会有一个 O(n) 解决方案。 (例如,在 C# 编译器中,您需要比较重载解决问题中的每一对方法以确定唯一的最佳方法;即使更好的方法关系是不传递的,也有一个 O(n) 算法。) 【参考方案1】:

听起来你可能想要这样的东西:

for (int i = 0; i < list.Count - 1; i++)

    for (int j = i + 1; j < list.Count; j++)
    
        // Use list[i] and list[j]
    

你绝对可以用 LINQ 做到这一点:

var pairs = from i in Enumerable.Range(0, list.Count - 1)
            from j in Enumerable.Range(i + 1, list.Count - i - 1)
            select Tuple.Create(list[i], list[j]);

我不确定它是否更清楚......

编辑:另一种效率较低但可能更清晰的替代方案:

var pairs = from i in Enumerable.Range(0, list.Count - 1)
            let x = list[i]
            from y in list.Skip(i + 1)
            select Tuple.Create(x, y);

【讨论】:

完美,比我想象的要简单得多。我会尽可能接受。谢谢你,但你是对的,LINQ 解决方案的可读性要差得多,而且很可能要慢得多。 谢谢,第一个版本(for循环)就像一个魅力!但是,我认为第二个版本(LINQ)有问题,因为它引发了 IndexOutOfRange 异常(两个版本之间的索引处理略有不同,但我没有时间弄清楚如何修复它)。 @Ishikawa:我认为这是一个错误,我现在已经修复了。【参考方案2】:

如果您使用的是 C# 7 或更高版本,则可以利用 ValueTuple 类型。它提供increased usability and performance。

public static IEnumerable<(T, T)> GetAllPairs<T>(IList<T> source)

    return source.SelectMany((_, i) => source.Where((_, j) => i < j),
        (x, y) => (x, y));

使用示例:

foreach ((int x, int y) in GetAllPairs(new[]  0, 1, 2 ))

    // Execute code
    Console.WriteLine($"Pair: x, y");

输出:

Pair: 0, 1
Pair: 0, 2
Pair: 1, 2

【讨论】:

以上是关于将每个元素与列表中的其他元素进行比较的主要内容,如果未能解决你的问题,请参考以下文章

如何将单个元素与集合或列表中的任何元素进行比较[重复]

带有链表的c中的堆栈-将元素与头部错误中的元素进行比较

比较列表haskell中的所有元素[重复]

如何比较和搜索列表中的元素与列表 SML 中的元组

将每个项目与 ArrayList 中的每个其他项目进行比较

查找数组的所有元素是不是不同的最快方法?