正常化数组的ConcurrentDictionary

问题描述:

我有一个数组的ConcurrentDictionary,其中每个数组具有相同的固定大小。它看起来像这样:ConcurrentDictionary<int, double[]> ItemFeatures正常化数组的ConcurrentDictionary

我想通过将所有值除以该列中值的最大值来标准化列表中的值。例如,如果我的列表大小为5,我希望第一个位置中的每个元素除以该位置中所有值的最大值,以此类推位置2。

我可以想到做到这一点的天真方式是,首先迭代列表中的每个列表和每个元素,并存储每个位置的最大值。然后再次遍历它们并将它们除以先前找到的最大值。

Linq中有没有更好的方法来做到这一点?这些字典会很大,所以效率越高/耗时越少越好。

+4

LINQ不会使代码做任何少,充其量它只是阻止你需要编写大量的代码做同样的事情,你需要遍历所有的数据来找到每个位置的最大值;如果不查看每个值,就无法找到最大值,这根本就没有办法解决。 – Servy

+0

当你这样做时,其他线程是否会访问'ConccurrentDictionary'?如果是这样,问题可能无法解决。 – Servy

+0

@Servy显然Linq不能创造奇迹。我的问题是,这是否会以某种方式更有效(就内存分配或时间而言),就像MATLAB中的矢量化比循环更有效。 – Antimony

不,这实际上是最有效的方法。最后,无论如何你都需要这样做,你不能跳过任何东西。你可以用LINQ编写它,但性能会更差,因为它会有很多函数调用和内存分配。 LINQ不会创造奇迹,它只是一种(有时)写作方式的更短的方式。

如果您的算法具有良好的“缓存局部性” - 换句话说,如果您以顺序方式访问计算机内存,什么才能加快速度。在.NET这样的环境中很难保证,但是像你描述的循环可能有接近它的最好机会。

+0

我希望C#中存在类似于矢量化的东西,它可以使事情比循环更快。 – Antimony

+0

什么是矢量化? :) –

+0

[什么是“矢量化”?](https://*.com/questions/1422149/what-is-vectorization) – Antimony

LINQ旨在查询数据,而不是修改数据。您可以使用一个小LINQ来计算最大值,但也差不多了:

var cols = ItemFeatures.First().Value.Length; 
var maxv = new double[cols]; 
for (var j1 = 0; j1 < cols; ++j1) 
    maxv[j1] = ItemFeatures.Values.Select(vs => vs[j1]).Max(); 

foreach (var kvp in ItemFeatures) 
    for (var j1 = 0; j1 < cols; ++j1) 
     kvp.Value[j1] /= maxv[j1]; 
+0

最后一个循环也可以省略: ItemFeatures = ItemFeatures.ToDictionary(x => x.Key,x => x.Value.Zip(maxv,(a,b)=> a/b).ToArray() );' 唯一的问题是,它不能使'ToDictionary()'和'ConcurrentDictionary'数据类型一致。 :( – Antimony

+0

这似乎是一个缺陷,而且,使用ToDictionary和ToArray并不会很有效,而且Zip看起来有点过分,为什么不只是'Values.Select(a => a/maxv)'? – NetMage