【问题标题】:Can I rely on the order of a SortedDictionary in Linq, and is it doing this efficiently?我可以依赖 Linq 中 SortedDictionary 的顺序,它是否有效地执行此操作?
【发布时间】:2009-02-11 19:39:35
【问题描述】:

当在 Linq 中使用 SortedDictionary 并遍历它提供的 KeyValuePair 时,我可以确保复杂的 linq 查询将按升序执行它吗?这是一个简短的,虽然有点令人困惑的例子:

Random r = new Random();
//build 100 dictionaries and put them into a sorted dictionary
//with "priority" as the key and it is a number 0-99.
SortedDictionary<int, Dictionary<int, double>> sortedDict = 
    new SortedDictionary<int, Dictionary<int, double>>();
for (int i = 0; i < 100; i++)
{
    Dictionary<int, double> dict = new Dictionary<int, double>();
    //create the dictionary and a random 10 k/v pairs
    for (int j = 0; j < 10; j++)
    {
        dict[r.Next(0, 100)] = r.NextDouble() * i * 10;
    }
    sortedDict[i] = dict;
}

IEnumerable<int> keys = Enumerable.Range(0, 100);

//the goal is to find the FIRST existence of the "key" inside one
//of the inner dictionaries going through the SortedDictionary IN ORDER
//this appears to work:
var qry = from key in keys
          from priority in sortedDict
          where priority.Value.ContainsKey(key)
          let value = priority.Value[key]
          group value by key into keyGroup
          let firstValue = keyGroup.First()
          select new { Key = keyGroup.Key, Value = firstValue };

// the result is as expected, a list of the numbers at most 0-99 and their
// value found in the dictionary with the lowest "priority"

问题:

  1. 它似乎有效,但我可以依赖这种行为吗?
  2. 这是有效率的,还是团队把它扔掉了?
  3. 添加“sortedDict.Reverse()”是否也能正常工作? (似乎)
  4. PLinq 将如何处理这个问题 - 它是否仍然保持一致?

如果不能保证这一点,我知道如何将“优先级”拉入分组并在事后按其排序。但我宁愿不...

【问题讨论】:

    标签: c# .net linq linq-to-objects


    【解决方案1】:
    1. 是的,您可以信任 SortedDictionary 的顺序。否则将毫无意义:)
    2. 如果没有“let”子句,效率会稍微高一些。做吧:

      var qry = from key in keys
                from priority in sortedDict
                where priority.Value.ContainsKey(key)
                let value = priority.Value[key]
                group value by key into keyGroup
                select new { Key = keyGroup.Key, Value = keyGroup.First() };
      

      但是,您仍然需要在字典中进行大量扫描。您基本上不想要从键到包含该键的优先级的反向映射吗?这可以更有效地构建。正如你所说,这个例子很混乱。如果您能告诉我们您想要在您的真实代码中实现什么,我们可能会想出更好的东西。 (如果确实是这种情况,我当然可以解决这个问题 - 我宁愿不这样做,然后发现现实非常不同!)

    3. 调用 Reverse() 确实会起作用 - 但它会缓冲所有数据。如果你想要它以相反的顺序,我建议你给 SortedDictionary 一个合适的 IComparer 开始。

    4. Parallel LINQ 在订单方面是“有趣的”。现在可能会有所不同,但我 had fun a while ago 在使用它绘制 Mandelbrot 集时...

    【讨论】:

    • 实际代码一如既往地复杂。我可能会在另一个问题中提出它,因为它没有直接关系
    【解决方案2】:

    这是一个answer,关于哪些 linq 方法保持顺序。

    目测查询,看起来你有:

      keys.SelectMany(...)
        .Where(...)
        .GroupBy(...)
        .Select(g => g.First())
        .Select(...);
    

    所有这些都会以某种方式保持排序。

    【讨论】:

      【解决方案3】:
      1. 是的,你可以。 SortedDictionary 无法取消排序。即使抛出异常,也保证保持排序
      2. 排序变得高效。您可以通过了解所使用的类型等领域知识来更有效地做到这一点,但在 99.99% 的情况下,这样做会非常不值得
      3. 是的:)
      4. 似乎我错了,plinq 的订购有问题。请参阅 jon 的帖子

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-07
        • 1970-01-01
        • 1970-01-01
        • 2015-10-11
        • 1970-01-01
        相关资源
        最近更新 更多