我知道c#中实例化的值类型数组会自动填充该类型的默认值(例如bool为false, int为0,等等)。

是否有一种方法来自动填充一个不是默认的种子值的数组?无论是在创建或之后的内置方法(如Java的Arrays.fill())?假设我想要一个默认为true的布尔数组,而不是false。是否有一个内置的方法来做到这一点,或者你只需要通过一个for循环迭代数组?

 // Example pseudo-code:
 bool[] abValues = new[1000000];
 Array.Populate(abValues, true);

 // Currently how I'm handling this:
 bool[] abValues = new[1000000];
 for (int i = 0; i < 1000000; i++)
 {
     abValues[i] = true;
 }

必须遍历数组并将每个值“重置”为true似乎效率不高。还有其他方法吗?也许通过翻转所有值?

在输入这个问题并思考之后,我猜默认值只是c#在幕后处理这些对象的内存分配的结果,所以我想这可能是不可能的。但我还是想确定一下!


当前回答

这也是可行的……但可能没有必要

 bool[] abValues = new bool[1000];
 abValues = abValues.Select( n => n = true ).ToArray<bool>();

其他回答

如果你使用的是。net Core, . net Standard >= 2.1,或者依赖于系统。内存包,你也可以使用Span<T>.Fill()方法:

var valueToFill = 165;
var data = new int[100];

data.AsSpan().Fill(valueToFill);

// print array content
for (int i = 0; i < data.Length; i++)
{
    Console.WriteLine(data[i]);
}

https://dotnetfiddle.net/UsJ9bu

我不知道框架方法,但你可以写一个快速助手来帮你做。

public static void Populate<T>(this T[] arr, T value ) {
  for ( int i = 0; i < arr.Length;i++ ) {
    arr[i] = value;
  }
}

创建一个包含1000个真值的新数组:

var items = Enumerable.Repeat<bool>(true, 1000).ToArray();  // Or ToList(), etc.

类似地,你可以生成整数序列:

var items = Enumerable.Range(0, 1000).ToArray();  // 0..999

下面的代码结合了小副本的简单迭代和Array。复印大份

    public static void Populate<T>( T[] array, int startIndex, int count, T value ) {
        if ( array == null ) {
            throw new ArgumentNullException( "array" );
        }
        if ( (uint)startIndex >= array.Length ) {
            throw new ArgumentOutOfRangeException( "startIndex", "" );
        }
        if ( count < 0 || ( (uint)( startIndex + count ) > array.Length ) ) {
            throw new ArgumentOutOfRangeException( "count", "" );
        }
        const int Gap = 16;
        int i = startIndex;

        if ( count <= Gap * 2 ) {
            while ( count > 0 ) {
                array[ i ] = value;
                count--;
                i++;
            }
            return;
        }
        int aval = Gap;
        count -= Gap;

        do {
            array[ i ] = value;
            i++;
            --aval;
        } while ( aval > 0 );

        aval = Gap;
        while ( true ) {
            Array.Copy( array, startIndex, array, i, aval );
            i += aval;
            count -= aval;
            aval *= 2;
            if ( count <= aval ) {
                Array.Copy( array, startIndex, array, i, count );
                break;
            }
        }
    }

使用int[]数组的不同数组长度的基准是:

         2 Iterate:     1981 Populate:     2845
         4 Iterate:     2678 Populate:     3915
         8 Iterate:     4026 Populate:     6592
        16 Iterate:     6825 Populate:    10269
        32 Iterate:    16766 Populate:    18786
        64 Iterate:    27120 Populate:    35187
       128 Iterate:    49769 Populate:    53133
       256 Iterate:   100099 Populate:    71709
       512 Iterate:   184722 Populate:   107933
      1024 Iterate:   363727 Populate:   126389
      2048 Iterate:   710963 Populate:   220152
      4096 Iterate:  1419732 Populate:   291860
      8192 Iterate:  2854372 Populate:   685834
     16384 Iterate:  5703108 Populate:  1444185
     32768 Iterate: 11396999 Populate:  3210109

第一列是数组大小,然后是使用简单迭代(@ jaredared实现)复制的时间。此方法的时间在此之后。 这些基准测试使用了一个由四个整数组成的结构数组

         2 Iterate:     2473 Populate:     4589
         4 Iterate:     3966 Populate:     6081
         8 Iterate:     7326 Populate:     9050
        16 Iterate:    14606 Populate:    16114
        32 Iterate:    29170 Populate:    31473
        64 Iterate:    57117 Populate:    52079
       128 Iterate:   112927 Populate:    75503
       256 Iterate:   226767 Populate:   133276
       512 Iterate:   447424 Populate:   165912
      1024 Iterate:   890158 Populate:   367087
      2048 Iterate:  1786918 Populate:   492909
      4096 Iterate:  3570919 Populate:  1623861
      8192 Iterate:  7136554 Populate:  2857678
     16384 Iterate: 14258354 Populate:  6437759
     32768 Iterate: 28351852 Populate: 12843259

我有点惊讶没有人做了非常简单,但超快的SIMD版本:

  public static void PopulateSimd<T>(T[] array, T value) where T : struct
  {
     var vector = new Vector<T>(value);
     var i = 0;
     var s = Vector<T>.Count;
     var l = array.Length & ~(s-1);
     for (; i < l; i += s) vector.CopyTo(array, i);
     for (; i < array.Length; i++) array[i] = value;
  }

基准测试:(数据来自于Framework 4.8,但Core3.1在统计上是相同的)

|     Method |       N |           Mean |          Error |        StdDev | Ratio | RatioSD |
|----------- |-------- |---------------:|---------------:|--------------:|------:|--------:|
| DarthGizka |      10 |      25.975 ns |      1.2430 ns |     0.1924 ns |  1.00 |    0.00 |
|       Simd |      10 |       3.438 ns |      0.4427 ns |     0.0685 ns |  0.13 |    0.00 |
|            |         |                |                |               |       |         |
| DarthGizka |     100 |      81.155 ns |      3.8287 ns |     0.2099 ns |  1.00 |    0.00 |
|       Simd |     100 |      12.178 ns |      0.4547 ns |     0.0704 ns |  0.15 |    0.00 |
|            |         |                |                |               |       |         |
| DarthGizka |    1000 |     201.138 ns |      8.9769 ns |     1.3892 ns |  1.00 |    0.00 |
|       Simd |    1000 |     100.397 ns |      4.0965 ns |     0.6339 ns |  0.50 |    0.00 |
|            |         |                |                |               |       |         |
| DarthGizka |   10000 |   1,292.660 ns |     38.4965 ns |     5.9574 ns |  1.00 |    0.00 |
|       Simd |   10000 |   1,272.819 ns |     68.5148 ns |    10.6027 ns |  0.98 |    0.01 |
|            |         |                |                |               |       |         |
| DarthGizka |  100000 |  16,156.106 ns |    366.1133 ns |    56.6564 ns |  1.00 |    0.00 |
|       Simd |  100000 |  17,627.879 ns |  1,589.7423 ns |   246.0144 ns |  1.09 |    0.02 |
|            |         |                |                |               |       |         |
| DarthGizka | 1000000 | 176,625.870 ns | 32,235.9957 ns | 1,766.9637 ns |  1.00 |    0.00 |
|       Simd | 1000000 | 186,812.920 ns | 18,069.1517 ns | 2,796.2212 ns |  1.07 |    0.01 |

可以看到,在小于10000个元素时速度要快得多,超过10000个元素时速度仅略慢。