【问题标题】:Normalize ConcurrentDictionary of arrays规范化数组的 ConcurrentDictionary
【发布时间】:2017-06-01 18:08:40
【问题描述】:

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

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

我能想到的最简单的做法是首先遍历每个列表和列表中的每个元素,然后存储每个位置的最大值。然后再次迭代它们并将它们除以先前找到的最大值。

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

【问题讨论】:

  • LINQ 不会让代码做更少的事情,充其量只会阻止你需要编写尽可能多的代码来做同样的事情,你是 going需要遍历所有数据以找到每个位置的最大值;如果不查看每个值,您就无法找到最大值,根本没有办法解决。
  • 在您执行此操作时,是否有任何其他线程将访问ConccurrentDictionary?如果是这样,问题很可能无法解决。
  • @Servy 显然 Linq 无法创造奇迹。我的问题是,这是否会更有效(在内存分配或时间方面),就像 MATLAB 中的向量化比循环更有效一样。
  • 不,不会同时访问它。
  • LINQ 是编写某些查询的便捷方式。任何你可以用它做的事情,你都可以不用它,但是没有它的代码可能会更长,或者更有可能传达的意思不太清楚。并非所有 LINQ 操作在底层都是循环(尽管其中很多只是一个循环),但它们大多都是相当简单的迭代过程,人们一直在没有 LINQ 的情况下编写。

标签: c# linq dictionary


【解决方案1】:

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

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

【讨论】:

  • 我希望 C# 中存在类似于矢量化的东西,它可以使事情比循环更快。
  • 什么是矢量化? :)
  • @Antimony - 把这个理论付诸实践:你可以确定你的值是如何在内存中布局的唯一方法是它们是否都在同一个数组中。所以有一个包含所有值的大数组,并使字典包含该数组的索引,而不是许多小数组。这将有双重好处 - 首先,您可以完全控制它们在内存中的布局方式;其次,减少分配/对象(每个单独的数组都是 GC 需要跟踪的单独对象)。然后当需要迭代时,在那个大数组而不是字典上进行。
  • 好吧,你也可以使用List<T>,它在内部使用一个数组并根据需要调整它的大小。或者可能是一些混合方案,其中您有一个大型固定大小数组的列表。
【解决方案2】:

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];

【讨论】:

  • 最后一个循环也可以消除:ItemFeatures = ItemFeatures.ToDictionary(x =&gt; x.Key, x =&gt; x.Value.Zip(maxv, (a, b) =&gt; a / b).ToArray()); 唯一的问题是,它无法协调ToDictionary()ConcurrentDictionary 数据类型。 :(
  • 这似乎是一个缺陷。此外,使用ToDictionaryToArray 无论如何都不会非常有效。而Zip 似乎有点矫枉过正,为什么不只是Values.Select(a =&gt; a / maxv) 呢?
猜你喜欢
  • 1970-01-01
  • 2021-06-18
  • 2019-10-03
  • 2019-08-09
  • 1970-01-01
  • 1970-01-01
  • 2016-06-04
  • 2020-07-05
  • 2021-12-13
相关资源
最近更新 更多