【问题标题】:LINQ tolookup using C#使用 C# 查找 LINQ
【发布时间】:2016-02-02 03:14:54
【问题描述】:

我有一个巨大的点数据类型列表和一个大小相等的双列表。大小可能在 1000000 左右。两个列表都来自不同的类。

List<Point> XYPair;  E.g. { (10,10),(10,10).......(20,20),(20,20).....}
List<double> ZValue; E.g. { 1.5, 1.6, .............7.8,8.7......}

我需要将唯一的 XY 对绘制为 XY 坐标。但是要为单个XY 应用markercolor,我需要为单个XY 查找所有相应的ZValue 并应用统计信息。 XYPairZValue 的索引匹配。是否可以使用 LINQ 来查找来有效地实现这一点,而不是像下面这样得到内存不足的预期错误?

目前我正在这样做:

GroupedPlotValues = XYLocation
    .Select(bv => bv.ElementAt(0))
    .Select((p, i) => new { Item1 = p, Item2 = i })
    .GroupBy(tp => tp.Item1, tp => tp.Item2)
    .ToDictionary(gr => gr.Key, gr => gr.ToList());


foreach (var item in GroupedPlotValues)
{
    var matched = item.Value.Intersect(MatchingIndexes).ToList();
    if (matched.Count != 0)
    {
        chart1.Series[0].Points.AddXY(item.Key.X, item.Key.Y);
        var singleZGroup = item.Value.Select(y => ZColumn[y]).ToList();
        ApplyStatistics(singleZGroup);
    }
}

【问题讨论】:

  • XYPair 是否与 ZValue 1:1 匹配?换言之,ZValue[0] 是否应用于 XYPair[0],ZValue[1] 是否应用于 XYPair[1],等等?另外,我不明白您的 GroupedPlotValues = ... 代码在做什么,因为代码中引用的类型似乎与问题开头的类型(XYPair 和 ZValue)无关
  • 是的!!! XYPair 与 ZValue 1:1 匹配。 GroupedPlotValues 正在创建一个字典,其中包含一个 xy 键和多个对应的 ZValues 索引。后面的代码,即 singleZGroup 获取匹配索引的对应值。
  • 为避免内存不足异常,您必须避免将所有数据加载到内存中。

标签: c# linq lookup


【解决方案1】:

为什么需要 LINQ?只需使用循环:

// Prepare the dictionary
Dictionary<Key, List<double>> dic = new Dictionary<Key, List<double>>();
for (int i =0; i< XYPair.Count; i++){
    // Create the key
    // Put ZValue[i] values in dictionary list element
}

// Use the Dictionary:

// Loop around dic keys
// If matched, apply statistics

【讨论】:

    【解决方案2】:

    如果你做了这样的事情呢?

    收集你的积分...

    var XY = new List<Point>()
    {
      { new Point(0, 0) },
      { new Point(10, 20) },
      { new Point(15, 5)},
      { new Point(0,0)},
      { new Point(10,20)}
    };
    

    收集您的 Z 值...

    var Z = new List<double>() { 0, 10, 20, 30, 40 };
    

    使用 Zip 构建一个包含 (Point, Z) 对的新列表,然后将结果序列转换为查找(类似于组字典),以 Point 值作为键。

    var lookup = XY.Zip(Z, (xy, z) => new { Point = xy, Z = z }).ToLookup(k => k.Point, v => v.Z);
    

    我不知道性能/内存特性是什么,但我认为它确实提供了您所追求的功能。

    我发现一些文章有助于制定这个答案:

    Implementing the Zip Operator in .NET 3.5 提供了一个您可以使用的 Zip 实现...

    正如我在下面的评论中所说,我的机器上的性能似乎很好,所以我的机器可能会更快,我的数据分布可能与你的不同,或者我认为“很好”的东西你可能会认为“慢” .话虽如此,我正在添加一些可能比您的版本更好(或可能不会)执行的代码。如果这还不够帮助,我不知道还要添加什么。此外,在您最初的问题中,您说您的内存不足。我建议的代码仍然会出现这种情况吗?

    我重写了你的代码:

    //Gather your position data
    var XY = new List<Point>();
    {
      { new Point(0, 0) },
      { new Point(10, 20) },
      { new Point(15, 5)},
      { new Point(0,0)},
      { new Point(10,20)}
    };
    
    //Gather your Z values ..
    var Z = new List<double>() { 0, 10, 20, 30, 40 };
    
    //Build the lookup
    var lookup = XY.Zip(Z, (xy, z) => new { Point = xy, Z = z }).ToLookup(k => k.Point, v => v.Z);
    
    //Process...
    //foreach unique XY (the Key of the lookup)
    //  Check to see if the XY is in a set of MatchingIndexes.  If not, continue.
    //  Add the unique point to the chart series.
    //  Get the Z values that correspond to the key (no need for ToList unless ApplyStatistics needs something more specialized than IEnumerable).
    //  Apply the Z values by calling ApplyStatistics
    //
    foreach (g in lookup.Select(g => g.Key))
    {
      var matched = MatchingIndexes.Select(i => i == g);
      if (!matched.Any()) continue;
      chart1.Series[0].Points.AddXY(g.X, g.Y);
      var singleZGroup = lookup[g];
      ApplyStatistics(singleZGroup);
    }
    

    请注意,我没有测试上面的处理代码。我希望它可以工作,并且我希望它可以完成您在原始代码中所做的等效工作。我对这是否“快”没有任何特别的期望。我的代码的主要目标是尽量减少复制数据的次数(通常通过调用 ToList)。

    祝你好运,我希望这会有所帮助。

    【讨论】:

    • 我正在使用 VS2008。所以 ZIP 不可用。我被指示使用哈希集。但是不知道怎么用
    • 我添加了一个 Zip 实现的链接,您可以使用该链接在 .Net 4.0 之前的版本上获取 Zip。
    • Wageoghe,我试过你的代码。像我的 lambda 查询这样的处理花费了几乎相同的时间。
    • 好吧,如果你有那么多元素(1000000 左右),这将需要一些时间。在我的机器上,我可以创建一个包含 1000000 个点和 1000000 个 Z 值的列表,执行上述查询(var lookup = ...)行,并实际评估它(通过对结果进行交互并计算唯一的数量键)在很短的时间内(我没有计时,但在我调试时没有明显的停顿)。我无法准确复制您正在做的事情,因为我对您如何处理 GroupedPlotValues 知之甚少...
    • 我确实有一些问题/建议...当您设置匹配时,您可能不必调用 ToList() (它会复制数据)。 MatchingIndexes 中有什么?有多少条目?创建 singleZGroup 时,您可能不必调用 ToList()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-13
    • 1970-01-01
    • 2013-12-21
    • 1970-01-01
    相关资源
    最近更新 更多