Question

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.).

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?

 // 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?

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!

Was it helpful?

Solution

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

OTHER TIPS

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

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

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:

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

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.

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

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

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

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!

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

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.

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 :

         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

         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

this also works...but might be unnecessary

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

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.

You can use Array.Fill in .NET Core 2.0+ and .NET Standard 2.1+.

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(...)

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.

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.

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:

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.

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.)

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

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

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

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

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

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

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

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

or

bool[] result = new bool[1000000];
new BitArray(1000000, true).CopyTo(result, 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.

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.

Boolean[] data = new Boolean[25];

new Action<Boolean[]>((p) => { BitArray seed = new BitArray(p.Length, true); seed.CopyTo(p, 0); }).Invoke(data);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top