如何用单个值填充/实例化c#数组?

时间:2022-09-02 08:46:23

I know that instantiated arrays of value types in C# are automatically populated with the default value of the type (e.g. false for bool, 0 for int, etc.).

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

Is there a way to auto-populate an array with a seed value that's not the default? Either on creation or a built-in method afterwards (like Java's Arrays.fill())? Say I wanted an boolean array that was true by default, instead of false. Is there a built-in way to do this, or do you just have to iterate through the array with a for loop?

是否有一种方法可以用非默认的种子值自动填充数组?要么是创建,要么是内置方法(比如Java的array .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;
 }

Having to iterate through the array and "reset" each value to true seems ineffecient. Is there anyway around this? Maybe by flipping all values?

必须遍历数组并将每个值“重置”到true似乎是无效的。这附近有吗?也许通过翻转所有的值?

After typing this question out and thinking about it, I'm guessing that the default values are simply a result of how C# handles the memory allocation of these objects behind the scenes, so I imagine it's probably not possible to do this. But I'd still like to know for sure!

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

20 个解决方案

#1


109  

Don't know of a framework method but you could write a quick helper to do it for you.

不知道框架方法,但可以编写一个快速助手来完成。

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

#2


154  

Enumerable.Repeat(true, 1000000).ToArray();

#3


48  

Create a new array with a thousand true values:

创建一个新的数组,包含一千个真实值:

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

Similarly, you can generate integer sequences:

同样,可以生成整数序列:

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

#4


21  

For large arrays or arrays that will be variable sized you should probably use:

对于大小可变的大数组或数组,您可能应该使用:

Enumerable.Repeat(true, 1000000).ToArray();

For small array you can use the collection initialization syntax in C# 3:

对于小数组,可以使用c# 3中的集合初始化语法:

bool[] vals = new bool[]{ false, false, false, false, false, false, false };

The benefit of the collection initialization syntax, is that you don't have to use the same value in each slot and you can use expressions or functions to initialize a slot. Also, I think you avoid the cost of initializing the array slot to the default value. So, for example:

集合初始化语法的好处是,您不必在每个槽中使用相同的值,您可以使用表达式或函数来初始化一个槽。另外,我认为可以避免将数组槽初始化为默认值的成本。举个例子:

bool[] vals = new bool[]{ false, true, false, !(a ||b) && c, SomeBoolMethod() };

#5


20  

If your array is so large you should use BitArray. It uses 1 bit for every bool instead of a byte (like in an array of bools) also you can set the all the bits to true with bit operators. Or just initialize on true. If you only need to do it once, it will only cost more though.

如果数组太大,应该使用位数组。它对每个bool使用1位,而不是一个字节(比如在bools数组中),您还可以使用位操作符将所有位设置为true。或者初始化为true。如果你只需要做一次,它只会花费更多。

System.Collections.BitArray falses = new System.Collections.BitArray(100000, false);
System.Collections.BitArray trues = new System.Collections.BitArray(100000, true);

// Now both contain only true values.
falses.And(trues);

#6


8  

Well after a little more googling and reading I found this:

在谷歌搜索和阅读之后,我发现:

bool[] bPrimes = new bool[1000000];
bPrimes = Array.ConvertAll<bool, bool>(bPrimes, b=> b=true);

Which is certainly closer to what I'm looking for. But I'm not sure if that's better than iterating through the original array in a for-loop and just changing the values. After a quick test in fact, it appears slower by about a factor of 5. So not really a good solution then!

这和我要找的很接近。但我不确定这是否比在for循环中遍历原始数组并只更改值更好。事实上,在快速测试之后,它看起来慢了大约5倍。所以这不是一个好的解决方案!

#7


7  

unfortunately I don't think there is a direct way, however I think you can write an extension method for the array class to do this

不幸的是,我认为没有直接的方法,但是我认为您可以为array类编写一个扩展方法来实现这一点

class Program
{
    static void Main(string[] args)
    {
        int[] arr = new int[1000];
        arr.Init(10);
        Array.ForEach(arr, Console.WriteLine);
    }
}

public static class ArrayExtensions
{
    public static void Init<T>(this T[] array, T defaultVaue)
    {
        if (array == null)
            return;
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = defaultVaue;
        }
    }
}

#8


6  

What about a parallel implementation

那么并行实现呢

public static void InitializeArray<T>(T[] array, T value)
{
    var cores = Environment.ProcessorCount;

    ArraySegment<T>[] segments = new ArraySegment<T>[cores];

    var step = array.Length / cores;
    for (int i = 0; i < cores; i++)
    {
        segments[i] = new ArraySegment<T>(array, i * step, step);
    }
    var remaining = array.Length % cores;
    if (remaining != 0)
    {
        var lastIndex = segments.Length - 1;
        segments[lastIndex] = new ArraySegment<T>(array, lastIndex * step, array.Length - (lastIndex * step));
    }

    var initializers = new Task[cores];
    for (int i = 0; i < cores; i++)
    {
        var index = i;
        var t = new Task(() =>
        {
            var s = segments[index];
            for (int j = 0; j < s.Count; j++)
            {
                array[j + s.Offset] = value;
            }
        });
        initializers[i] = t;
        t.Start();
    }

    Task.WaitAll(initializers);
}

When only initializing an array the power of this code can't be seen but I think you should definitely forget about the "pure" for.

当仅仅初始化一个数组时,这段代码的威力是看不到的,但是我认为您应该完全忘记“纯的”for。

#9


5  

The code below combines simple iteration for small copies and Array.Copy for large copies

下面的代码结合了小副本和数组的简单迭代。对于大型副本副本

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

The benchmarks for different array length using an int[] array are :

使用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

The first columns is the array size, followed by the time of copying using a simple iteration ( @JaredPared implementation ). The time of this method is after that. These are the benchmarks using an array of a struct of four integers

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

         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

#10


5  

Or... you could simply use inverted logic. Let false mean true and vice versa.

还是……你可以简单地使用反向逻辑。让假意味着真,反之亦然。

Code sample

代码示例

// bool[] isVisible = Enumerable.Repeat(true, 1000000).ToArray();
bool[] isHidden = new bool[1000000]; // Crazy-fast initialization!

// if (isVisible.All(v => v))
if (isHidden.All(v => !v))
{
    // Do stuff!
}

#11


3  

this also works...but might be unnecessary

这也可以…但可能是不必要的

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

#12


3  

If you're planning to only set a few of the values in the array, but want to get the (custom) default value most of the time, you could try something like this:

如果您计划只在数组中设置一些值,但是大多数情况下希望获得(自定义)默认值,您可以尝试如下方法:

public class SparseArray<T>
{
    private Dictionary<int, T> values = new Dictionary<int, T>();

    private T defaultValue;

    public SparseArray(T defaultValue)
    {
        this.defaultValue = defaultValue;
    }

    public T this [int index]
    {
      set { values[index] = value; }
      get { return values.ContainsKey(index) ? values[index] ? defaultValue; }
    }
}

You'll probably need to implement other interfaces to make it useful, such as those on array itself.

您可能需要实现其他接口以使其有用,比如数组本身上的接口。

#13


2  

There is no way to set all elements in an array as a single operation, UNLESS, that value is the element types default value.

无法将数组中的所有元素设置为单个操作,除非该值是元素类型的默认值。

Eg, if it is an array of integers you can set them all to zero with a single operation, like so: Array.Clear(...)

如果它是一个整数数组,那么您可以通过单个操作将它们全部设置为零,例如:Array.Clear(…)

#14


2  

If you can invert your logic you can use the Array.Clear() method to set the boolean array to false.

如果您可以反转您的逻辑,您可以使用Array.Clear()方法将布尔数组设置为false。

        int upperLimit = 21;
        double optimizeMe = Math.Sqrt(upperLimit);

        bool[] seiveContainer = new bool[upperLimit];
        Array.Clear(seiveContainer, 0, upperLimit);

#15


1  

I realize I'm late to the party but here's an idea. Write a wrapper which has conversion operators to and from the wrapped value so that it can be used as a stand-in for the wrapped type. This was actually inspired by the silly-sounding answer from @l33t.

我知道我参加聚会迟到了,但我有个主意。编写一个包装器,该包装器具有与包装值之间的转换操作符,以便将其用作包装类型的替代。这实际上是受到了@l33t愚蠢的回答的启发。

First (coming from C++) I realized that in C# a default ctor is not called when the elements of an array are constructed. Instead -- even in the presence of a user-defined default constructor! -- all array elements are zero-initialized. That did surprise me.

首先(来自c++)我意识到在c#中,当一个数组的元素被构建时,默认的ctor不会被调用。相反——即使是在用户定义的默认构造函数的情况下!——所有数组元素都是零初始化的。这确实让我吃惊。

So a wrapper class which simply provides a default ctor with the desired value would work for arrays in C++ but not in C#. A workaround is to let the wrapper type map 0 to the desired seed value upon conversion. That way zero initialized values appear to be initialized with the seed for all practical purposes:

因此,简单地提供具有所需值的默认ctor的包装器类可以在c++中使用,但在c#中不能。一个解决方案是让包装器类型在转换时映射0到所需的种子值。这样一来,零初始化值就会被种子初始化,以达到所有实际目的:

public struct MyBool
{
    private bool _invertedValue;

    public MyBool(bool b) 
    {   
        _invertedValue = !b;
    }

    public static implicit operator MyBool(bool b)
    {
        return new MyBool(b);
    }

    public static implicit operator bool(MyBool mb)
    {
        return !mb._invertedValue;
    }

}

static void Main(string[] args)
{
        MyBool mb = false; // should expose false.
        Console.Out.WriteLine("false init gives false: " 
                              + !mb);

        MyBool[] fakeBoolArray = new MyBool[100];

        Console.Out.WriteLine("Default array elems are true: " 
                              + fakeBoolArray.All(b => b) );

        fakeBoolArray[21] = false;
        Console.Out.WriteLine("Assigning false worked: " 
                              + !fakeBoolArray[21]);

        fakeBoolArray[21] = true;
        // Should define ToString() on a MyBool,
        // hence the !! to force bool
        Console.Out.WriteLine("Assigning true again worked: " 
                              + !!fakeBoolArray[21]);
}

This pattern is applicable to all value types. One could for example map 0 to 4 for ints if initialization with 4 was desired etc.

此模式适用于所有值类型。例如,如果需要初始化4,可以映射0到4。

I'd love to make a template of it as would be possible in C++, providing the seed value as template parameter, but I understand that's not possible in C#. Or am I missing something? (Of course in C++ mapping is not necessary at all because one can provide a default ctor which will be called for array elements.)

我很想在c++中创建一个模板,提供种子值作为模板参数,但是我知道在c#中这是不可能的。还是我漏掉了什么?(当然,在c++映射中根本没有必要,因为可以提供一个用于数组元素的默认ctor。)

FWIW, here's a C++ equivalent: https://ideone.com/wG8yEh .

FWIW,这里有一个C+等效项:https://ideone.com/wG8yEh。

#16


0  

There are some more answers on this (duplicate?) question: What is the equivalent of memset in C#?

关于这个(重复的?)问题还有更多的答案:c#中的memset是什么?

Someone has benchmarked the alternatives (they included an unsafe version, but they didn't try memset): http://techmikael.blogspot.co.uk/2009/12/filling-array-with-default-value.html

有人对替代方案进行了基准测试(其中包括一个不安全的版本,但他们没有尝试memset): http://techmikael.blogspot.co.uk/2009/12/filling-array-with- defaultvalue.html

#17


0  

Here is another appraoch with System.Collections.BitArray which has such a constructor.

这是另一个与System.Collections有关的appraoch。有构造函数的位数组。

bool[] result = new BitArray(1000000, true).Cast<bool>().ToArray();

or

bool[] result = new bool[1000000];
new BitArray(1000000, true).CopyTo(result, 0);

#18


0  

Make a private class inside where you make the array and the have a getter and setter for it. Unless you need each position in the array to be something unique, like random, then use int? as an array and then on get if the position is equal null fill that position and return the new random value.

在创建数组的地方创建一个私有类,并为其设置一个getter和setter。除非您需要数组中的每个位置都是唯一的,比如random,那么使用int?作为一个数组,如果位置等于null,就填充这个位置并返回新的随机值。

IsVisibleHandler
{

  private bool[] b = new bool[10000];

  public bool GetIsVisible(int x)
  {
  return !b[x]
  }

  public void SetIsVisibleTrueAt(int x)
  {
  b[x] = false //!true
  }
}

Or use

或使用

public void SetIsVisibleAt(int x, bool isTrue)
{
b[x] = !isTrue;
}

As setter.

setter。

#19


0  

I tested it for myself and it seems that the Enumerable.Repeat method is ten times faster.

我自己测试了一下,似乎是可数的。重复方法要快十倍。

    [Test]
    public void Create_array_with_Array_Copy() {
        var size = 3000 * 30000;
        var arr = new int [size];
        var val = 0xFF;

        FillArray<int> (arr, val);
    }

    [Test]
    public void Create_array_with_loop () {
        var size    = 3000 * 30000;
        var arr     = new int [size];
        var val     = 0xFF;

        Populate<int> (arr, val);
    }

    [Test]
    public void Create_array_with_Repeat () {
        var size = 3000 * 30000;
        var arr = new int [size];
        var val = 0xFF;

        Enumerable.Repeat<int> (val, size);
    } 

    static void FillArray<T> (T [] arr, T fillValue) {
        int i = 0;
        if (arr.Length > 16) {
            {
                do {
                    arr [i++] = fillValue;
                } while (i < arr.Length);
                while (i + 16 < arr.Length) {
                    Array.Copy (arr, 0, arr, i, 16);
                    i = i + 16;
                }
            }
            while (i < arr.Length) {
                arr [i++] = fillValue;
            }
        }
    }

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

regards Ronny

认为罗尼

#20


-2  

Boolean[] data = new Boolean[25];

new Action<Boolean[]>((p) => { BitArray seed = new BitArray(p.Length, true); seed.CopyTo(p, 0); }).Invoke(data);

#1


109  

Don't know of a framework method but you could write a quick helper to do it for you.

不知道框架方法,但可以编写一个快速助手来完成。

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

#2


154  

Enumerable.Repeat(true, 1000000).ToArray();

#3


48  

Create a new array with a thousand true values:

创建一个新的数组,包含一千个真实值:

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

Similarly, you can generate integer sequences:

同样,可以生成整数序列:

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

#4


21  

For large arrays or arrays that will be variable sized you should probably use:

对于大小可变的大数组或数组,您可能应该使用:

Enumerable.Repeat(true, 1000000).ToArray();

For small array you can use the collection initialization syntax in C# 3:

对于小数组,可以使用c# 3中的集合初始化语法:

bool[] vals = new bool[]{ false, false, false, false, false, false, false };

The benefit of the collection initialization syntax, is that you don't have to use the same value in each slot and you can use expressions or functions to initialize a slot. Also, I think you avoid the cost of initializing the array slot to the default value. So, for example:

集合初始化语法的好处是,您不必在每个槽中使用相同的值,您可以使用表达式或函数来初始化一个槽。另外,我认为可以避免将数组槽初始化为默认值的成本。举个例子:

bool[] vals = new bool[]{ false, true, false, !(a ||b) && c, SomeBoolMethod() };

#5


20  

If your array is so large you should use BitArray. It uses 1 bit for every bool instead of a byte (like in an array of bools) also you can set the all the bits to true with bit operators. Or just initialize on true. If you only need to do it once, it will only cost more though.

如果数组太大,应该使用位数组。它对每个bool使用1位,而不是一个字节(比如在bools数组中),您还可以使用位操作符将所有位设置为true。或者初始化为true。如果你只需要做一次,它只会花费更多。

System.Collections.BitArray falses = new System.Collections.BitArray(100000, false);
System.Collections.BitArray trues = new System.Collections.BitArray(100000, true);

// Now both contain only true values.
falses.And(trues);

#6


8  

Well after a little more googling and reading I found this:

在谷歌搜索和阅读之后,我发现:

bool[] bPrimes = new bool[1000000];
bPrimes = Array.ConvertAll<bool, bool>(bPrimes, b=> b=true);

Which is certainly closer to what I'm looking for. But I'm not sure if that's better than iterating through the original array in a for-loop and just changing the values. After a quick test in fact, it appears slower by about a factor of 5. So not really a good solution then!

这和我要找的很接近。但我不确定这是否比在for循环中遍历原始数组并只更改值更好。事实上,在快速测试之后,它看起来慢了大约5倍。所以这不是一个好的解决方案!

#7


7  

unfortunately I don't think there is a direct way, however I think you can write an extension method for the array class to do this

不幸的是,我认为没有直接的方法,但是我认为您可以为array类编写一个扩展方法来实现这一点

class Program
{
    static void Main(string[] args)
    {
        int[] arr = new int[1000];
        arr.Init(10);
        Array.ForEach(arr, Console.WriteLine);
    }
}

public static class ArrayExtensions
{
    public static void Init<T>(this T[] array, T defaultVaue)
    {
        if (array == null)
            return;
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = defaultVaue;
        }
    }
}

#8


6  

What about a parallel implementation

那么并行实现呢

public static void InitializeArray<T>(T[] array, T value)
{
    var cores = Environment.ProcessorCount;

    ArraySegment<T>[] segments = new ArraySegment<T>[cores];

    var step = array.Length / cores;
    for (int i = 0; i < cores; i++)
    {
        segments[i] = new ArraySegment<T>(array, i * step, step);
    }
    var remaining = array.Length % cores;
    if (remaining != 0)
    {
        var lastIndex = segments.Length - 1;
        segments[lastIndex] = new ArraySegment<T>(array, lastIndex * step, array.Length - (lastIndex * step));
    }

    var initializers = new Task[cores];
    for (int i = 0; i < cores; i++)
    {
        var index = i;
        var t = new Task(() =>
        {
            var s = segments[index];
            for (int j = 0; j < s.Count; j++)
            {
                array[j + s.Offset] = value;
            }
        });
        initializers[i] = t;
        t.Start();
    }

    Task.WaitAll(initializers);
}

When only initializing an array the power of this code can't be seen but I think you should definitely forget about the "pure" for.

当仅仅初始化一个数组时,这段代码的威力是看不到的,但是我认为您应该完全忘记“纯的”for。

#9


5  

The code below combines simple iteration for small copies and Array.Copy for large copies

下面的代码结合了小副本和数组的简单迭代。对于大型副本副本

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

The benchmarks for different array length using an int[] array are :

使用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

The first columns is the array size, followed by the time of copying using a simple iteration ( @JaredPared implementation ). The time of this method is after that. These are the benchmarks using an array of a struct of four integers

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

         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

#10


5  

Or... you could simply use inverted logic. Let false mean true and vice versa.

还是……你可以简单地使用反向逻辑。让假意味着真,反之亦然。

Code sample

代码示例

// bool[] isVisible = Enumerable.Repeat(true, 1000000).ToArray();
bool[] isHidden = new bool[1000000]; // Crazy-fast initialization!

// if (isVisible.All(v => v))
if (isHidden.All(v => !v))
{
    // Do stuff!
}

#11


3  

this also works...but might be unnecessary

这也可以…但可能是不必要的

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

#12


3  

If you're planning to only set a few of the values in the array, but want to get the (custom) default value most of the time, you could try something like this:

如果您计划只在数组中设置一些值,但是大多数情况下希望获得(自定义)默认值,您可以尝试如下方法:

public class SparseArray<T>
{
    private Dictionary<int, T> values = new Dictionary<int, T>();

    private T defaultValue;

    public SparseArray(T defaultValue)
    {
        this.defaultValue = defaultValue;
    }

    public T this [int index]
    {
      set { values[index] = value; }
      get { return values.ContainsKey(index) ? values[index] ? defaultValue; }
    }
}

You'll probably need to implement other interfaces to make it useful, such as those on array itself.

您可能需要实现其他接口以使其有用,比如数组本身上的接口。

#13


2  

There is no way to set all elements in an array as a single operation, UNLESS, that value is the element types default value.

无法将数组中的所有元素设置为单个操作,除非该值是元素类型的默认值。

Eg, if it is an array of integers you can set them all to zero with a single operation, like so: Array.Clear(...)

如果它是一个整数数组,那么您可以通过单个操作将它们全部设置为零,例如:Array.Clear(…)

#14


2  

If you can invert your logic you can use the Array.Clear() method to set the boolean array to false.

如果您可以反转您的逻辑,您可以使用Array.Clear()方法将布尔数组设置为false。

        int upperLimit = 21;
        double optimizeMe = Math.Sqrt(upperLimit);

        bool[] seiveContainer = new bool[upperLimit];
        Array.Clear(seiveContainer, 0, upperLimit);

#15


1  

I realize I'm late to the party but here's an idea. Write a wrapper which has conversion operators to and from the wrapped value so that it can be used as a stand-in for the wrapped type. This was actually inspired by the silly-sounding answer from @l33t.

我知道我参加聚会迟到了,但我有个主意。编写一个包装器,该包装器具有与包装值之间的转换操作符,以便将其用作包装类型的替代。这实际上是受到了@l33t愚蠢的回答的启发。

First (coming from C++) I realized that in C# a default ctor is not called when the elements of an array are constructed. Instead -- even in the presence of a user-defined default constructor! -- all array elements are zero-initialized. That did surprise me.

首先(来自c++)我意识到在c#中,当一个数组的元素被构建时,默认的ctor不会被调用。相反——即使是在用户定义的默认构造函数的情况下!——所有数组元素都是零初始化的。这确实让我吃惊。

So a wrapper class which simply provides a default ctor with the desired value would work for arrays in C++ but not in C#. A workaround is to let the wrapper type map 0 to the desired seed value upon conversion. That way zero initialized values appear to be initialized with the seed for all practical purposes:

因此,简单地提供具有所需值的默认ctor的包装器类可以在c++中使用,但在c#中不能。一个解决方案是让包装器类型在转换时映射0到所需的种子值。这样一来,零初始化值就会被种子初始化,以达到所有实际目的:

public struct MyBool
{
    private bool _invertedValue;

    public MyBool(bool b) 
    {   
        _invertedValue = !b;
    }

    public static implicit operator MyBool(bool b)
    {
        return new MyBool(b);
    }

    public static implicit operator bool(MyBool mb)
    {
        return !mb._invertedValue;
    }

}

static void Main(string[] args)
{
        MyBool mb = false; // should expose false.
        Console.Out.WriteLine("false init gives false: " 
                              + !mb);

        MyBool[] fakeBoolArray = new MyBool[100];

        Console.Out.WriteLine("Default array elems are true: " 
                              + fakeBoolArray.All(b => b) );

        fakeBoolArray[21] = false;
        Console.Out.WriteLine("Assigning false worked: " 
                              + !fakeBoolArray[21]);

        fakeBoolArray[21] = true;
        // Should define ToString() on a MyBool,
        // hence the !! to force bool
        Console.Out.WriteLine("Assigning true again worked: " 
                              + !!fakeBoolArray[21]);
}

This pattern is applicable to all value types. One could for example map 0 to 4 for ints if initialization with 4 was desired etc.

此模式适用于所有值类型。例如,如果需要初始化4,可以映射0到4。

I'd love to make a template of it as would be possible in C++, providing the seed value as template parameter, but I understand that's not possible in C#. Or am I missing something? (Of course in C++ mapping is not necessary at all because one can provide a default ctor which will be called for array elements.)

我很想在c++中创建一个模板,提供种子值作为模板参数,但是我知道在c#中这是不可能的。还是我漏掉了什么?(当然,在c++映射中根本没有必要,因为可以提供一个用于数组元素的默认ctor。)

FWIW, here's a C++ equivalent: https://ideone.com/wG8yEh .

FWIW,这里有一个C+等效项:https://ideone.com/wG8yEh。

#16


0  

There are some more answers on this (duplicate?) question: What is the equivalent of memset in C#?

关于这个(重复的?)问题还有更多的答案:c#中的memset是什么?

Someone has benchmarked the alternatives (they included an unsafe version, but they didn't try memset): http://techmikael.blogspot.co.uk/2009/12/filling-array-with-default-value.html

有人对替代方案进行了基准测试(其中包括一个不安全的版本,但他们没有尝试memset): http://techmikael.blogspot.co.uk/2009/12/filling-array-with- defaultvalue.html

#17


0  

Here is another appraoch with System.Collections.BitArray which has such a constructor.

这是另一个与System.Collections有关的appraoch。有构造函数的位数组。

bool[] result = new BitArray(1000000, true).Cast<bool>().ToArray();

or

bool[] result = new bool[1000000];
new BitArray(1000000, true).CopyTo(result, 0);

#18


0  

Make a private class inside where you make the array and the have a getter and setter for it. Unless you need each position in the array to be something unique, like random, then use int? as an array and then on get if the position is equal null fill that position and return the new random value.

在创建数组的地方创建一个私有类,并为其设置一个getter和setter。除非您需要数组中的每个位置都是唯一的,比如random,那么使用int?作为一个数组,如果位置等于null,就填充这个位置并返回新的随机值。

IsVisibleHandler
{

  private bool[] b = new bool[10000];

  public bool GetIsVisible(int x)
  {
  return !b[x]
  }

  public void SetIsVisibleTrueAt(int x)
  {
  b[x] = false //!true
  }
}

Or use

或使用

public void SetIsVisibleAt(int x, bool isTrue)
{
b[x] = !isTrue;
}

As setter.

setter。

#19


0  

I tested it for myself and it seems that the Enumerable.Repeat method is ten times faster.

我自己测试了一下,似乎是可数的。重复方法要快十倍。

    [Test]
    public void Create_array_with_Array_Copy() {
        var size = 3000 * 30000;
        var arr = new int [size];
        var val = 0xFF;

        FillArray<int> (arr, val);
    }

    [Test]
    public void Create_array_with_loop () {
        var size    = 3000 * 30000;
        var arr     = new int [size];
        var val     = 0xFF;

        Populate<int> (arr, val);
    }

    [Test]
    public void Create_array_with_Repeat () {
        var size = 3000 * 30000;
        var arr = new int [size];
        var val = 0xFF;

        Enumerable.Repeat<int> (val, size);
    } 

    static void FillArray<T> (T [] arr, T fillValue) {
        int i = 0;
        if (arr.Length > 16) {
            {
                do {
                    arr [i++] = fillValue;
                } while (i < arr.Length);
                while (i + 16 < arr.Length) {
                    Array.Copy (arr, 0, arr, i, 16);
                    i = i + 16;
                }
            }
            while (i < arr.Length) {
                arr [i++] = fillValue;
            }
        }
    }

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

regards Ronny

认为罗尼

#20


-2  

Boolean[] data = new Boolean[25];

new Action<Boolean[]>((p) => { BitArray seed = new BitArray(p.Length, true); seed.CopyTo(p, 0); }).Invoke(data);