使用c#进行LINQ查找
本文关键字:查找 LINQ 进行 使用 | 更新日期: 2023-09-27 18:11:34
我有一个点数据类型的大列表和一个大小相等的双列表。大小可以在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,我需要为单个XY
查找所有相应的ZValue
并应用统计数据。XYPair
和ZValue
匹配的索引。是否有可能使用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);
}
}
为什么需要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
如果你做了这样的事情呢?
收集你的分数…
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);
我不知道性能/内存特性是什么,但我认为它确实提供了你想要的功能。
我发现一些文章有助于形成这个答案:
LINQ ToDictionary和ToLookup有什么区别
LINQ: tollookup vs ToDictionary
在。net 3.5中实现Zip操作符提供了一个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)。
祝你好运,希望对你有所帮助。