【问题标题】:Multi-dimensional arrays -- getting the same coding power as 1-dimensional arrays多维数组——获得与一维数组相同的编码能力
【发布时间】:2014-06-04 02:25:54
【问题描述】:

我主要使用 C# 进行编程,但这似乎适用于所有 .NET。

我的情况是,使用多维数组似乎是最合乎逻辑的事情,但我觉得使用它们让我无法使用 .NET。

  • System.LINQ 不适用于多维数组。 (ETA:但请参阅 Nico Schertler 的评论)
  • System.Array 的实用方法在处理多维数组方面非常有限。
  • 似乎没有任何方法可以为多维数组编写扩展方法。(ETA:这是错误的,请参阅 Nico Schertler 的评论)
  • 几年前,多维数组的速度要慢得多——现在仍然如此吗? Why are multi-dimensional arrays in .NET slower than normal arrays?(ETA:是的,请参阅 Tim S 的回答)

我知道我可以选择使用扁平数组,但这与数据并不匹配。我也知道我可以选择循环遍历所有维度并进行复制,但是当语言和编译器很智能时,这似乎是一种古老的做事方式。所以我的问题是:

  • 是否有一种标准方法可以将 LINQ(或等效功能)与多维数组(将二维数组转换为数据库或List<Tuple>)一起使用?
  • 是否有标准方法来分割多维数组(返回单个超曲面或一系列超曲面)?
  • 排序。我找到了C# rectangular array sort;但这并不适用,因为我确实提前知道了尺寸。

ETA:我说的是在 C# 中声明为 double[,] dataTable = new double[5,3]; 的“原生”数组类型,而不是锯齿状数组或任何其他嵌套类。

【问题讨论】:

  • 可以为多维数组编写扩展方法。例如。我最近实现了IEnumerable<double> Linearize(this double[,] arr)。通过这样的扩展方法,您可以使用最常见的 LINQ 方法而没有很多开销。
  • @Nico 您可以这样做,但您必须为每个等级编写单独的扩展方法。没有办法编写一个适用于所有等级的扩展方法。
  • 为什么这个问题没有立即关闭,因为它是基于意见的?是否可以用(非任意选择的)事实来回答这个问题?
  • @AnotherParker 我建议您在问题中非常清楚您的要求并删除任何基于意见的内容。到目前为止,我支持我的近距离投票(基于意见)。对于您的第二个子问题,我仍然认为过于宽泛。我很欣赏这个问题的精神,但我认为它不适合这个网站。
  • CLR 没有针对 MD 阵列进行优化,尽管这显然是可能的。为什么?根据我的经验,MD 阵列非常罕见。我宁愿拥有非常快的 SZ 阵列和慢速 MD 阵列,也不愿两者都同样快。为什么要将资金投入到非常很少使用的功能领域?我刚刚搜索了 150 KLOC 的代码驱动生产网站,我唯一能找到 MD 数组的地方是在 levenshtein 距离的代码中。

标签: .net arrays


【解决方案1】:

它们是非常笨拙的数据结构。在任何语言中,不仅仅是 C#。它们的一些固有问题:

  • 没有有意义的方法来迭代它们。顺序本质上是模棱两可的,无法表示新维度开始迭代。这就是扼杀它们在 Linq 中使用的原因。
  • 计算元素的地址本质上是昂贵的。 N 维数组需要 N-1 次乘法和 N 次长度查找以及边界检查才能找到元素
  • 它们方式容易使用错误,访问元素的顺序非常糟糕地使用 CPU 缓存
  • 向量在 CLR 中得到了很多优化,而多维数组则没有,因为获得的收益太少了
  • 当然 Array 很尴尬,因为索引器的数量是可变的。

所以不要使用它们。锯齿状数组和列表列表是合理的选择。减去语法糖,可以说 C# 太多了。

【讨论】:

    【解决方案2】:

    首先,LINQ 设计用于处理序列。通常,人们将序列视为一维实体。因此,它不适用于多维数据类型也就不足为奇了。尽管 LINQ 可能可能被扭曲以假定行优先顺序并遍历多维数组,但这并不是普遍接受的处理事物的方式。即便如此,您也可以让 LINQ 很好地处理多维数组,但不能处理列表列表(即List<List<int>>)。那会打开一大袋虫子。总而言之,您最好编写自己的枚举器,将您的多维结构转换为一维序列。

    一维数组通常比多维数组快,因为您需要做的边界检查更少。这与锯齿状数组通常更快的原因相同。但这并不是普遍正确的。请参阅我的博客条目Are jagged arrays faster than rectangular arrays?

    我没有看到任何证据表明微软正在“推动”我们使用一维数组而不是多维数组。一维数组更简单,因此更容易优化。而且,由于一维数组的使用频率更高,它们将受到更多关注。

    我怀疑Array 类的许多函数不适用于多维数组的原因是因为它们对多维没有意义,或者因为它们通常没有足够的用处来保证实施它们。在处理多维数组时,我很少需要这些函数。

    【讨论】:

      【解决方案3】:

      是的,是的。这是使用 C# 5/.NET 4.5 重新运行该代码,通过 LINQPad 运行,并进行了优化。

      sum took 00:00:01.7903305
      sum took 00:00:02.9606820 (165%)
      sum took 00:00:01.7093106 (95%)
      

      结论有些主观,但我同意你的观点,多维数组是二等公民。在大多数情况下,锯齿状数组 (double[][]) 和列表 (List<List<double>>) 似乎是首选方法。

      有时代码是用锯齿状或多维数组编写的,这些数组一开始就不应该是这样的......例如List<MyModel>Dictionary<double, double> 可能是更好的选择。

      【讨论】:

        【解决方案4】:

        我会说不。因为我是 Dictionary 类的狂热用户。尤其是字典中的字典。

        是的,由于嵌套和其他原因,它的运行速度往往会慢一些。但代码本身往往非常易读,并且适合协作。

        【讨论】:

        • 对不起,我想我不够具体——我不是在谈论 Dictionary、List 或任何其他类,我是在谈论语言的数组特性(也许这是System.Array)
        猜你喜欢
        • 1970-01-01
        • 2010-11-17
        • 1970-01-01
        • 2011-01-31
        • 1970-01-01
        • 2020-02-05
        • 2015-08-30
        • 2015-03-15
        • 1970-01-01
        相关资源
        最近更新 更多