【问题标题】:Select subset of elements by comparing them with each other in LINQ通过在 LINQ 中相互比较来选择元素的子集
【发布时间】:2011-02-26 20:47:06
【问题描述】:

我正在尝试构建一个 LINQ 查询,该查询将采用元素列表,并根据列表中元素之间的比较,选择满足特定条件的元素。像这样:

var subset = set.SomeLinqQuery((e1,e2) => e1 == e2);

subset 现在包含set 中的所有e1,其中e1 == e2。有任何想法吗?本来我只是想有一个嵌套循环,但我意识到在 LINQ 中一定有办法做到这一点。

【问题讨论】:

  • 所以您想查找集合中的所有重复项?设置什么类型的集合?如果是“集合”,则不允许重复。
  • 我想我的名字有点不对,它只是一个列表。

标签: c# linq


【解决方案1】:

您将需要一种方法来从原始集合中生成独特项对。这是我的实现:

/// <summary>
/// Returns an enumeration of tuples containing all unique pairs of distinct
/// elements from the source collection. For example, the input sequence
/// { 1, 2, 3 } yields the pairs [1,2], [1,3] and [2,3] only.
/// </summary>
public static IEnumerable<Tuple<T, T>> UniquePairs<T>(this IEnumerable<T> source)
{
    if (source == null)
        throw new ArgumentNullException("source");
    return uniquePairsIterator(source);
}
private static IEnumerable<Tuple<T, T>> uniquePairsIterator<T>(IEnumerable<T> source)
{
    // Make sure that 'source' is evaluated only once
    IList<T> arr = source as IList<T> ?? source.ToList();
    for (int i = 0; i < arr.Count - 1; i++)
        for (int j = i + 1; j < arr.Count; j++)
            yield return new Tuple<T, T>(arr[i], arr[j]);
}

现在您可以轻松实现您想要的:

var results = set.UniquePairs()
                 .Where(pair => pair.Item1 == pair.Item2)
                 .Select(pair => pair.Item1);

【讨论】:

  • @Timwi - 我在查询示例第三行的pair.Item 上收到编译器错误。
  • @Timwi - 另一件事;假设我在元素中有一个double 属性,并且我希望results 包含该属性最高的pair.ItemX。我该怎么做?
  • 啊,我们创建了不必要的抽象来隐藏简单的嵌套循环。当一个简单而明显的结构就足够时,我只是不明白需要使用闪亮和新的(er)语言功能。
  • @Bevin:来吧,你必须至少自己考虑一下。仅仅通过询问,您将无法获得其他人编写的所有代码。显然是pair =&gt; Math.Max(pair.Item1, pair.Item2)。
  • @Ed:然后阅读一些关于惰性评估的内容,例如。或者关于聚合。
【解决方案2】:

使用交叉连接

from e1 in set
from e2 in set
where e1 == e2
select e1

这为您提供了与重复项的身份联合

你可能想要更多这样的东西

from e1 in set
from e2 in set
where e1 != e2
where e1.key == e2.key
select e1

【讨论】:

  • 你认为你可以用 LINQ 方法来表达吗?
  • @Bevin,您可以使用@Timwi 的答案中的SelectMany,但我更喜欢查询语法的可读性。
  • 编辑后的答案假定所有项目都是不同的。想象一下,您有一个整数列表,并且您想要一个包含所有模 5 相同的整数对的列表。当且仅当原始集合包含多个 47 时,返回对 (47, 47) 可能很重要。您的解决方案将从初始集合中删除重复的整数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多