【问题标题】:Linq Join list with itself distinctlyLinq Join 列表与自身明显不同
【发布时间】:2022-10-14 04:10:16
【问题描述】:

我有一个值列表,比如说A、B 和 C.我想将它与自身结合以获得所有不同的组合,考虑到一个值不能是它本身并且A-B是相同的B-A

最终结果应该是A-B、A-C、B-C不是一个完整的交叉产品A-A, A-B, A-C, B-A, B-B, B-C, C-A, C-B, C-C

在传统代码中,我想出了以下内容

var myList = new List<string> { "A", "B", "C" };
for(var i=0; i < myList.Count; i++)
    for (var j=i+1; j < myList.Count; j++)
        //Do Something

是否有任何 LINQ 等价物?我主要是在寻求更有意义和人类可读的实现。

【问题讨论】:

标签: linq


【解决方案1】:

我在 LInQ 中找到了一种方法,但我不认为它具有更有意义的 nr 可读性,而且从性能的角度来看,它的速度要慢 6 到 7 倍。

from item1 in myList
from item2 in myList.SkipWhile(x => x != item1).Skip(1)
select (item1, item2)

我首先认为表现的主要原因是LInQ 版本不好是因为它仍然运行一个完整的交叉产品,但我的简单基准似乎不同意。

Count V1 V2 Ratio V1/item V2/item V1/item^2 V2/item^2
1 10 125 455 3,640 12,500 45,500 1,250 4,550
2 10 124 440 3,548 12,400 44,000 1,240 4,400
3 30 976 3034 3,109 32,533 101,133 1,084 3,371
4 30 975 3023 3,101 32,500 100,767 1,083 3,359
5 50 2702 8088 2,993 54,040 161,760 1,081 3,235
6 50 2763 8155 2,952 55,260 163,100 1,105 3,262
7 70 5393 15708 2,913 77,043 224,400 1,101 3,206
8 70 5416 15740 2,906 77,371 224,857 1,105 3,212
9 90 8993 25908 2,881 99,922 287,867 1,110 3,199
10 90 8983 25869 2,880 99,811 287,433 1,109 3,194

基准代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Benchmarks
{
    class Program
    {
        static void Main(string[] args)
        {
            for (var i = 1; i <= 10; i+=2)
            {
                CrossProduct(i, Enumerable.Range(1,10*i).Select(x => x.ToString()).ToList());
            }

            _ = Console.Read();
        }

        private static void CrossProduct(int iterations, IList<string> data)
        {
            var v1 = CrossProductV1(data);
            var v2 = CrossProductV2(data);
            Console.WriteLine($"{iterations} | DataCount: {data.Count}	| V1:{v1}* | V2:{v2}");
            v2 = CrossProductV2(data);
            v1 = CrossProductV1(data);
            Console.WriteLine($"{iterations+1} | DataCount: {data.Count}	| V1:{v1}  | V2:{v2}*");
        }

        private static long CrossProductV1(IList<string> data)
        {
            var sw = System.Diagnostics.Stopwatch.StartNew();

            for (var repeatIndex = 0; repeatIndex < 100000; repeatIndex++)
            {
                List<object> result = new List<object>();
                for (var i = 0; i < data.Count; i++)
                    for (var j = i + 1; j < data.Count; j++)
                        result.Add((data[i], data[j]));
            }
            return sw.ElapsedMilliseconds;
        }
        private static long CrossProductV2(IList<string> data)
        {
            var sw = System.Diagnostics.Stopwatch.StartNew();

            for (var repeatIndex = 0; repeatIndex < 100000; repeatIndex++)
            {
                List<object> result = null;
                result = (from item1 in data
                          from item2 in data.SkipWhile(x => x != item1).Skip(1)
                          select (object)(item1, item2)).ToList();
            }

            return sw.ElapsedMilliseconds;
        }
    }
}

【讨论】:

    猜你喜欢
    • 2015-10-21
    • 2016-12-10
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-05
    相关资源
    最近更新 更多