如何只将列表中的每个元素与自身进行一次比较

时间:2012-08-06 01:42:38

标签: c# linq linq-to-objects

不完全确定如何最好地表达这个问题。如何仅将列表中的每个元素与同一列表中的每个元素进行一次比较。

例如:

var textlist = ["a", "b", "c"];
var intersecting = from string a in textlist
                   from string b in textlist
                   where a != b && a.SomeCondition(b)
                   select new
                   {
                       object1 = a,
                       object2 = b
                   };

假设“a”将“True”赋予“SomeCondition”和“b”,我希望最终结果是:

[["a, b"]]

现在它将是:

[["a, b"], ["b, a"]]

这可以通过Linq查询吗?

4 个答案:

答案 0 :(得分:2)

您可以使用值比较 - 即仅处理>的对。湾您甚至可以将a != b替换为a > b,因为会暗示不平等:

var textlist = ["a", "b", "c"];
var intersecting = from string a in textlist
               from string b in textlist
               where a > b && (a.SomeCondition(b) || b.SomeCondition(a))
               select new
               {
                   object1 = a,
                   object2 = b
               };

答案 1 :(得分:1)

我通过添加CompareTo condtion:

来提出您想要的结果
string[] textlist = new string[] {"a", "b", "c"};
var intersecting =  from string a in textlist
                    from string b in textlist
                    where ((a != b) && (a.CompareTo(b) == -1)) // && a.SomeCondition(b)
                    select new { object1 = a, object2 = b }
                    ;

intersecting.Dump("Result");

这是结果的屏幕截图

enter image description here

您可以删除额外的//以取消注释您的状况。

答案 2 :(得分:1)

一种方法是将每个元素与仅位于其后面的元素进行比较:

string[] textlist = {"a", "b", "c"};
var intersecting = from aIndex in Enumerable.Range(0, textlist.Count())
                   from b in textlist.Skip(aIndex + 1)
                   let a = textlist.ElementAt(aIndex)
                   where a != b && a.SomeCondition(b)
                   select new
                   {
                       object1 = a,
                       object2 = b
                   };

注意:此解决方案以及使用LINQ的此问题的大多数解决方案,如果在枚举成本高昂的IEnumerable上使用,将会非常低效。

答案 3 :(得分:0)

如果你不能使用>这是另一种方法。您的对象之间或您的集合可以包含重复项。它的工作原理是使用SelectMany的重载以及将索引传递给集合中项目的Where。我意识到它不是那么可读,但我认为它更强大。

        string[] data = "A,A,B,C".Split(',');
        var query = data.SelectMany((x1, i1) => data.Where((x2, i2) => i2 > i1 && x1.SomeCondition(x2)).Select(x2 => new { object1 = x1, object2 = x2 }));
        foreach (var item in query) Console.WriteLine(item.object1 + "," + item.object2);