【问题标题】:Linq thenby running indefinitelyLinq 然后无限期地运行
【发布时间】:2014-03-03 18:22:43
【问题描述】:

我有一个函数,它只是为了以易于理解的方式打印出频繁项集的字典。目标是首先按字典键的大小排序,然后按数字列表的字典顺序。问题出现在 ThenBy 语句中,因为注释掉的“hello”将无限期地打印出来。如果我将 ThenBy 更改为不使用比较器并简单地使用另一个 int 或字符串值,它工作正常,所以我显然做错了什么。

public static void printItemSets(Dictionary<List<int>, int> freqItemSet)
{
    List<KeyValuePair<List<int>, int>> printList = freqItemSet.ToList();
    printList = printList.OrderBy(x => x.Key.Count)
                         .ThenBy(x => x.Key, new ListComparer())
                         .ToList();
}

ListComparer的代码如下:

public class ListComparer: IEqualityComparer<List<int>>, IComparer<List<int>>
{
    public int Compare(List<int> a, List<int> b)
    {
        int larger = a.Count > b.Count ? 1: -1;
        for (int i = 0; i < a.Count && i < b.Count; i++)
        {
            if (a[i] < b[i])
            {
                return -1;
            }
            else if (a[i] > b[i])
            {
                return 1;
            }
            else { }
        }
        return larger;
    }
}

非常简单的测试用例:

int[] a = {1, 3, 5};
int[] b = { 2, 3, 5 };
int[] c = { 1, 2, 3, 5 };
int[] d = { 2, 5 };
int[] e = { 1, 3, 4 };
List<int> aL = a.ToList<int>();
List<int> bL = b.ToList<int>();
List<int> cL = c.ToList<int>();
List<int> dL = d.ToList<int>();
List<int> eL = e.ToList<int>();
Dictionary<List<int>, int> test = new Dictionary<List<int>, int>(new ListComparer());
test.Add(aL, 1);
test.Add(bL, 1);
test.Add(cL, 1);
test.Add(dL, 1);
test.Add(eL, 1);

【问题讨论】:

  • 看起来它最终应该终止。不过,它似乎确实有可能特别慢。您是否尝试过将其作为单元测试运行?您是否尝试过使用只有几个元素的模拟字典来确保代码按预期运行?
  • 我目前正在使用只有 4 个项目的字典对其进行测试,因此,它应该足够小。由于它只是一个打印功能,而且我并不期待特别大的列表,它可能仍然可以。我主要处于“草稿”模式,只是想写一些可以正常工作的东西。
  • 您的比较器无法处理相同的项目。如果项目相等,则这两个项目的顺序决定了哪个被认为是“更大”。比较器因此不是“自反的”。这是排序算法所依赖的属性。第一行应该是var larger = a.Count.CompareTo(b.Count);。也就是说,它不会导致您看到的问题。
  • 字典是如何填充的?显示代码。我的猜测是,当你应该对不同的列表有多个引用时,你有一堆对同一个列表的引用,而这些引用是你一遍又一遍地变异的。
  • 因为项目来自字典,所以不可能有两个相等的列表。不过,我可以将该检查放入比较函数中。

标签: c# linq


【解决方案1】:

问题是ListComparer 没有检查数组是否相同。对于xy,同一个数组被传入了两次。检查xy 是否相等将解决您的问题。

【讨论】:

    【解决方案2】:

    您的比较器不处理相等的项目。如果项目相等,则两个项目的顺序决定了哪个被认为是“更大”。比较器因此不是“自反的”。自反性是排序算法所依赖的属性。

    第一行应该是var larger = a.Count.CompareTo(b.Count);,这样真正相等的列表将返回0,而不是-11

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-22
      • 1970-01-01
      • 1970-01-01
      • 2019-02-04
      • 2023-01-12
      • 1970-01-01
      相关资源
      最近更新 更多