【问题标题】:Nested while loop alternatives嵌套的 while 循环替代方案
【发布时间】:2013-08-23 06:37:36
【问题描述】:

我编写了一些遵循以下基本模式的代码。我正在寻找是否有更好、更简洁或性能更好的想法来实现相同的目标。目标是将一个列表中的项目与另一个列表中的项目进行比较,并在它们匹配时执行操作。我让它工作的唯一方法是下面的想法,但我是 c# 和 .net 的新手,我不确定是否有更好的方法。

list A
list B
int counter;
int counter2;
while (counter < comparison item)
{
    while (counter2 < comparison item 2)
    {
        if (A[counter] == B[counter2])
        {
            // do stuff
        }
        counter2++;
    }
    counter++;
}

【问题讨论】:

  • LINQ 是一种可能,但在功能上是一样的。
  • 您也可以预先对列表进行排序并进行合并连接类型的操作。根据列表的大小以及您计划执行的操作类型,它可能会更快。与往常一样,测量。

标签: c# .net loops iteration


【解决方案1】:

这种双循环结构很简单,但性能不佳。问题在于比较的数量:如果第一组有N 项目,第二组有M,那么就会有N*M 比较。每组有 1,000 个项目,我们谈论的是 1,000,000 次比较。

更好的方法是对第一个集合中的项目进行散列,然后在散列中搜索第二个集合中的项目。由于散列是在摊销的常数时间内完成的,因此您可以在 M+N 操作中执行此操作,或者对于两组各 1,000 个项目大约 2,000 个:

var setA = new HashSet<int>(listA);
foreach (var b in listB) {
    if (setA.Contains(b)) {
        ...
    }
}

LINQ 库让您可以用更少的代码行来做到这一点:

foreach (var ab in listA.Intersect(listB)) {
    ...
}

【讨论】:

  • 谢谢你的回答,对于第二个例子,你会使用列表作为List对象还是HashSet对象?
  • @wondergoat77 传递给 LINQ 的容器无关紧要:它在内部使用基于哈希的容器进行合并,将输入视为 IEnumerable&lt;T&gt;
【解决方案2】:

如果您不需要更改列表,那么您应该使用foreach 循环。

foreach (var itemA in A)
{
    foreach (var itemB in B)
    {
        if (itemA == itemB) {}
    }
}

如果您确实需要更改列表,那么您应该使用for 循环。

for (var i = 0; i < A.Count; i++) 
{
    for (var j = 0; j < B.Count; j++)
    {
        if (A[i] == B[j]) {}
    }
}

如果这两个列表已排序,您可以通过按顺序浏览列表更有效地做到这一点。

int i = 0;
int j = 0;

while (A.Length <= i && B.Length <= j)
{
    if (A[i] == B[j]) 
    {
        // items are equal
        i++;
        j++;
    }
    else if (A[i] > B[j]) // Comparison of the ordered value, could be a property on the item.
    {
        j++; // increment B's counter
    }
    else
    {
        i++; // increment A's counter
    }
}

【讨论】:

    猜你喜欢
    • 2021-05-25
    • 1970-01-01
    • 1970-01-01
    • 2017-09-03
    • 2015-06-29
    • 2018-04-15
    • 2020-03-09
    • 2020-01-15
    • 1970-01-01
    相关资源
    最近更新 更多