我有一个庞大的点数据类型列表和一个相同大小的双列表。大小可能在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
对绘制为X
和Y
坐标。但是要为单XY
应用markercolor,我需要查找该单ZValue
的所有相应XY
并应用统计信息。 XYPair
和ZValue
的索引匹配。是否可以使用 LINQ tolookup来有效地实现这一点,而不是通过如下所示获得outofmemory expction错误?
目前我这样做:
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);
}
}
答案 0 :(得分:2)
为什么需要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
答案 1 :(得分: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)。
祝你好运,我希望这会有所帮助。