使用嵌套的For循环和Linq

时间:2019-01-24 20:49:32

标签: c# linq loops for-loop nested

我在下面的代码中运行良好,可以找到列表中彼此之间相似度为±2的项目。我想使用2个版本来检查哪个版本运行速度更快。

版本a)具有嵌套的For循环,如下代码。但是,代码的最后一部分具有!List.Contains(),我希望将其替换为另一个For循环,因为Contains()增加了4500个滴答声,而其他2个嵌套的for循环仅需要1500个滴答声。因此,如果有人可以帮助用另一个for循环替换Contains()并提供相同的结果,我将不胜感激。

版本b),但使用LINQ。

在两个版本中,输出列表intTestResult中的项目必须为:(1、2、8、9、10、12)

        int intOffset = 2;
        List<int> intTest = new List<int> { 1, 2, 5, 8, 9, 10, 12, 15, 19, 24 };
        List<int> intTestResult = new List<int>();

        var S1 = Stopwatch.StartNew();

        for (int a = 0; a < intTest.Count; a++)

            {
                int int1 = intTest[a];

                for (int b = 0; b < intTest.Count; b++)

                {

                int int2 = intTest[b];

                if (int1 + intOffset >= int2 && int1 - intOffset <= int2 && int1 != int2)


                    {

                    if (!intTestResult.Contains(int1))                      

                        intTestResult.Add(int1);

                    }
                }
            }

        S1.Stop();

        Console.WriteLine("Ticks = " + S1.ElapsedTicks);                    

/ *经历过壁虱6000

intTestResult项目为(1、2、8、9、10、12)* /

2 个答案:

答案 0 :(得分:1)

替换:

if (!intTestResult.Contains(int1))                      
    intTestResult.Add(int1);

使用

bool contains = false;
for(int c = 0; c < intTestResult.Count; c++)
{
    if(int1 == intTestResult[c])
    {
        contains = true;
        break;
    }
}

if(!contains)
    intTestResult.Add(int1);

答案 1 :(得分:1)

害怕衡量效果的方法是错误的。

  1. 首先,您应该多次执行方法,例如在循环中。因为首次执行将始终花费更多时间,并且可能可以从计算中排除首次循环。

  2. 使用大量数据进行处理。许多有效的数据结构在处理少量数据时速度较慢,而处理大量数据时速度很快。

  3. 如果您的应用程序无法处理大量数据,那么您根本不需要测试性能。 只需编写对其他开发人员(您自己)来说都易于阅读和理解的代码。我会说“写出可以被人脑快速处理的代码”。

使用HashSet<int>Enumerable.Aggregate的方法

// Helper method to check if two numbers within offset
private IEnumerable<int> WithinOffset(int? previous, int current, int offset)
{
    if (previous.HasValue == false)
    {
        yield break;
    }

    var difference = Math.Abs(previous.Value, current);
    if (difference > 0 && difference <= offset)
    {
        yield return previous.Value;
        yield return current;
    }
}

var clock = Stopwatch.Start();

var offset = 2;
var result = 
    givenData.OrderBy(number => number)
             .Aggregate(
                 (All: Enumerable.Empty<int>(), Last: default(int?)),
                 (summary, current) => 
                 {
                     var withinOffset = WithinOffset(summery.Last, current, offset);
                     var all = summary.All.Concat(withinOffset);
                     return (all, current);
                 },
                 (summary) => summary.All.ToHashSet().ToList());
clock.Stop();

var ticks = clock.ElapsedTicks;

如果我按照您的方法进行测量,但会提供包含1000个项目的列表

var template = new[] { 1, 2, 5, 8, 9, 10, 12, 15, 19, 24 }
var givenData = 
    Enumerable.Range(0, 100)
              .Select(i => i * 100)
              .Select(i => template.Select(number => number + i))
              .SelectMany(number => number)
              .ToList();


// Approach with accepted answer
// Elapsed ticks = 11517000 (1.1517 seconds)

// Approach with HashSet, OrderBy and Aggregate
// Elapsed ticks = 2202000 (0.2202 seconds)