如何使用另一个数组创建和初始化一个数组?

19

为了创建和初始化一个数组,我目前这样做:

void Foo( int[] a )
{
    int[] b = new int[ a.Length ];
    for ( int i = 0; i < a.Length; ++i )
        b[ i ] = a[ i ];

    // Other code ...
}

在C#中有没有更短或更惯用的方法来完成这个任务?

如果可以像C++一样用一个语句完成就太好了:

vector<int> b( a );

如果无法在一个语句中完成,那我将接受现状 :-)


2
你不能直接使用 Array.Copy 吗? - M.Babcock
应该有一种方法可以直接复制所有内存...在C++中。https://dev59.com/kW865IYBdhLWcg3wQMWW - T.T.T.
http://stackoverflow.com/questions/5655553/whats-the-most-efficient-way-to-copy-elements-of-a-c-sharp-multidimensional-arr - T.T.T.
https://dev59.com/km435IYBdhLWcg3w-1V_ - T.T.T.
Tommy:我的问题与其他人不同,因为我正在寻找C++中vector<int> b(a)的C#等效项。 - Ashwin Nanjappa
6个回答

28

我喜欢使用LINQ来实现这个:

int[] b = a.ToArray();

话虽如此,如果在紧密循环中使用,则Array.Copy具有更好的性能:

int[] b = new int[a.Length];
Array.Copy(a, b, a.Length);

编辑:

如果能够用单个语句完成这个操作,就像在C++中一样,那将是很棒的。

vector b(a);

在C#中,相应的代码为:

List<int> b = new List<int>(a);

List<T> 是 C# 中等同于 std::vector<T> 的类型。上述构造函数适用于任何IEnumerable<T>,包括另一个List<T>、数组(T[])等。


7

使用Array.Copy来复制一个数组。

     int[] source = new int[5];
     int[] target = new int[5];
     Array.Copy(source, target, 5);

3

Clone()和ToArray()在语法上很方便,因为您不需要预分配目标数组,但就性能而言,Array.Copy()是最快的方法(请参见下面的警告)。

Array.Copy()之所以如此快,是因为它不会分配任何内存。然而,如果您要求每次将数组复制到新的内存区域中,则Array.Copy()不再是最快的方法。

以下是我的性能结果:

Copy: 0 ms
Copy (with allocation): 449 ms
Clone: 323 ms
ToArray: 344 ms

以下是我使用的代码:

const int arrayLength = 100000;
const int numberCopies = 1000;
var a = new int[arrayLength];
var b = new int[arrayLength];

var stopwatch = new Stopwatch();
for (var i = 0; i < numberCopies; i++) {
    Array.Copy(a, b, arrayLength);
}
Console.WriteLine($"Copy: {stopwatch.ElapsedMilliseconds} ms");

stopwatch.Restart();
for (var i = 0; i < numberCopies; i++) {
    var c = new int[arrayLength];
    Array.Copy(a, c, arrayLength);
}
Console.WriteLine($"Copy (with allocation): {stopwatch.ElapsedMilliseconds} ms");

stopwatch.Restart();
for (var i = 0; i < numberCopies; i++) {
    b = (int[]) a.Clone();
}
Console.WriteLine($"Clone: {stopwatch.ElapsedMilliseconds} ms");

stopwatch.Restart();
for (var i = 0; i < numberCopies; i++) {
    b = a.ToArray();
}
Console.WriteLine($"ToArray: {stopwatch.ElapsedMilliseconds} ms");

1

同时也可以尝试使用默认的Clone()函数,该函数是从IClonable接口实现的。

int[] b = a.Clone() as int[];

0

您可以通过创建新的空数组或使用给定的数组来轻松实现此目标。

int[] arr = { 1, 2, 0, 3, 4, 5, 0, 6, 0, 7, 8, 9, 0 };
int[] newArray = new int[arr.Length];

Array.Copy(arr, newArray, arr.Length);

foreach (var item in newArray)
{
   if(item != 0)
   Console.WriteLine(item);
}   

0

这个解决方案并不是最快的,也不是最优雅的,但如果你需要跳过原始数组中的一些元素,或者对它们进行转换,你可以使用Linq来实现。

var sourceArray = new int[] {1,2,3,4,5,6,7,8,9 };
var targetArray = sourceArray.Select(s => s).ToArray();

// targetArray now contains 1,2,3,4,5,6,7,8,9

承认吧,这看起来有点愚蠢,除非你需要在复制期间执行某种操作

var sourceArray = new int[] {1,2,3,4,5,6,7,8,9 };
var targetArray = sourceArray.Skip(1).Take(3).Select(s => s*s+4).ToArray();

// targetArray now contains 8,13,20

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接