views:

1715

answers:

10

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

Is there a way to autopopulate an array with a seed value that's not the default? Either on creation or a built in method afterwards (I believe Java has something like Array.Fill() which does this)? 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!

+10  A: 

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;
  }
}
JaredPar
That's a pretty good idea Jared - I'm definitely thinking I may be adding something like this to my extension library if no other answers pop up!
patjbs
+3  A: 
var items = Enumerable.Range(0, 1000).ToArray(); // Or ToList() or whatever...

sorry need to read whole question...

var items = Enumerable.Repeat<bool>(true, 1000).ToArray();
J.13.L
The user wants to set a single default value all elements of the array, not create a new array with increasing values.
JaredPar
I saw that as soon as I posted... Here is the right answer...
J.13.L
Not bad, but it's still slower than a for loop by about a factor of 4x
patjbs
patjbs in theory in the future Enumerable.Repeat will perform faster because it will use a parallel implementation.
Petar Petrov
A: 

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!

patjbs
that's similar to what you're trying to do, except its making a function call for each element in your array. It may look much nicer syntactically, but its doing a lot more work...
Nader Shirazie
yeah, it's looking like a simply for loop does the job just about as well as anything else
patjbs
+12  A: 
Enumerable.Repeat(true, 1000000).ToArray();
Rony
While this works it's not really a good solution because it's very slow; it's about 4 times slower than iterating with a for loop in fact.
patjbs
yes that's true, when we consider performance the for loop is faster
Rony
Who needs fast when you can have cool.
Erin
+2  A: 

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;
        }
    }
}
bashmohandes
I'm liking the extension idea the more I dig into this. Sometimes the upfront and simple solution is really the best!
patjbs
A: 

this also works...but might be unnecessary

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

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() };
LBushkin
+1  A: 

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);
MrFox
A: 

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.

Petar Petrov
A: 

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.

Douglas