【问题标题】:Is there an efficient equivalent of Array.Copy for arrays with different numbers of dimensions?对于具有不同维数的数组,是否有有效的 Array.Copy 等效项?
【发布时间】:2014-03-31 04:46:54
【问题描述】:

我有两个数组:

T[] array1D;
T[,] array2D;

它们每个都有相同的元素总数。

如果这些数组的维数相同,那么我可以简单地使用 Array.Copy 将数据从一个复制到另一个。但由于它们的维度数量不同,根据 MSDN 文档,我不能:

sourceArray 和destinationArray 参数的维数必须相同。

在分析了我的代码后,我确定单独复制每个元素对于我的目的来说太慢了。那么,是否有替代 Array.Copy 的替代方案,可以在不同维度的数组之间进行复制,其性能与 Array.Copy 相似?

谢谢!

(编辑)根据要求,这是我单独复制每个元素的代码:

        int iMax = array2D.GetLength(0);
        int jMax = array2D.GetLength(1);
        int index = 0;
        for(int i = 0; i < iMax; ++i)
        {
            for(int j = 0; j < jMax; ++j)
            {
                array1D[index] = array2D[i, j];
                ++index;
            }
        }

【问题讨论】:

  • 贴出你用来复制的代码。还可以考虑包装一个数组,您只需在其中转换维数。
  • @Blam 已发布,谢谢。
  • 您是否尝试过Buffer.BlockCopy 来展平二维数组? Jon Skeet's answer中的示例代码。
  • 代码有多难写?您可以使用指针、不安全和原始 memcpy...

标签: c# .net


【解决方案1】:

这应该比您的代码运行得更快,但不确定多快。让我们知道:

public static T[] FlattenArray<T>(T[,] array)
{
    List<T> values = new List<T>(array.Length);

    foreach (var item in array)
    {
        values.Add(item);
    }

    return values.ToArray();
}

编辑:

这应该会更快。任何更快的东西都可能需要一些非托管的解决方案。

public static T[] FlattenArray<T>(T[,] array)
{
    T[] values = new T[array.Length];

    Buffer.BlockCopy(array, 0, values, 0, values.Length);

    return values;
}

【讨论】:

  • 为什么不直接创建数组呢?
  • @hvd 因为那样你就不能用 foreach 来做,否则它毫无意义,因为你必须增加索引,这将导致代码与 OPs 解决方案几乎相同。
  • 您只需要一个索引,而不是 OP 代码中的三个索引,因此它仍然很可能是一个改进。 (foreach (var item in array) values[index++] = item;) 无论如何,首先创建一个列表,填充它,然后从该列表创建一个数组的开销可能足够高,以至于它比直接创建数组的任何解决方案都更糟糕。但是您的编辑(在对该问题的评论中也提到过)避免了这个问题。
  • 不应该是Buffer.BlockCopy(array, 0, values, 0, values.Length * sizeof(T));吗?
  • 谢谢!! Buffer.BlockCopy 在我的情况下有效,因为 T 恰好是非托管类型。如果 T 是引用类型,我仍然希望看到一个有效的答案。
【解决方案2】:

这可能会中断,因为不确定您是否可以像这样并行单个对象(数组)
我尝试使用少量元素,只使用字符串

我喜欢 BlockCopy 的答案

private String[] ArrayCopy(String[,] array2D)
{
    int iMax = array2D.GetLength(0);
    int jMax = array2D.GetLength(1);
    String[] array1D = new String[iMax * jMax];
    for (int i = 0; i < iMax; ++i)
    {
        //System.Diagnostics.Debug.WriteLine("    parallel " + i.ToString());
        Parallel.For(0, jMax, j =>
        {
            //System.Diagnostics.Debug.WriteLine("  j loop parallel " + j.ToString() + " " + array2D[i,j]);
            array1D[(i * jMax) + j] = array2D[i, j];
        });
    }
    return array1D;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-26
    • 2011-11-08
    • 2016-05-11
    相关资源
    最近更新 更多