20

Surprisingly for me

new string[count];

is filled with nulls. So I came up with

var emptyStrings = Enumerable.Range(0, count)
    .Select(a => String.Empty)
    .ToArray();

which is very verbose. Isn't there a shorcut?

1
  • 2
    the question would be why do you need default empty string? Commented Nov 24, 2010 at 15:38

2 Answers 2

46

You can use Enumerable.Repeat:

 string[] strings = Enumerable.Repeat(string.Empty, count).ToArray();

(But be aware that creating a string array of the correct size and looping will give better performance.)

Sign up to request clarification or add additional context in comments.

1 Comment

Also worth noting that explicitly creating the array and looping only needs a few characters more than using Enumerable.Repeat.
1

Handling multiple dimensions

I had to work with a bunch of string arrays that had to be initialized to empty, some multi-dimensional. This was a bit of a pain so I created the following which you may find useful:

public static class StringArrayExtensions
{
    public static string[] InitializeWithEmptyStrings(this string[] source)
    {
        // the jitter will hoist source.Length out of the loop automatically here
        for(int i = 0; i < source.Length; i++)
            source[i] = string.Empty;

        return source;          
    }

    public static string[,] InitializeWithEmptyStrings(this string[,] source)
    {
        var len0 = source.GetLength(0);
        var len1 = source.GetLength(1);
        for (int i = 0; i < len0; i++)
            for (int j = 0; j < len1; j++)
                source[i,j] = string.Empty;

        return source;
    }
}

Then you can do something like:

class Foo
{
    public string[,] Data = new string[2,2].InitializeWithEmptyStrings();
}

Update - One method to handle arbitrary dimensions

I thought it would be fun to try and generalise this to combine creating the array and initializing it, using a general purpose method. It's not going to be as fast as the above, but it will handle arbitrary numbers of dimensions:

public static class ArrayFactory
{
    public static TArrayType CreateArrayInitializedWithEmptyStrings<TArrayType>(
        params int[] dimensionLengths) where TArrayType : class
    {
        var dimensions = dimensionLengths.Select(l => Enumerable.Range(0, l));
        var array = Array.CreateInstance(typeof(string), dimensionLengths);
        foreach (var indices in CartesianProduct(dimensions))
            array.SetValue(string.Empty, indices.ToArray());

        return (array as TArrayType);
    }

    private static IEnumerable<IEnumerable<T>> CartesianProduct<T>(
    IEnumerable<IEnumerable<T>> dimensions)
    {
        return dimensions.Aggregate(
            (IEnumerable<IEnumerable<T>>)new T[][] { new T[0] },
            (acc, input) =>
                from prevDimension in acc
                from item in input
                select prevDimension.Concat(new T[] { item }));
    }
}

This method requires the desired array as a generic parameter - use like so:

// this would create a string[2,3,4,2] initialized with empty strings
ArrayFactory.CreateArrayInitializedWithEmptyStrings<string[,,,]>(2,3,4,2);

Props to Ian Griffiths for his article series which was the source of the generalized CartesianProduct method.

Update 2

Here's a refined version of the Cartesian Product that used recursion to get the index combinations:

public static class ArrayFactory
{
    public static TArrayType CreateArrayInitializedWithEmptyStrings<TArrayType>(
            params int[] dimensionLengths) where TArrayType : class
    {
        var array = Array.CreateInstance(typeof(string), dimensionLengths);
        foreach (var indices in CartesianProduct(dimensionLengths))
            array.SetValue(string.Empty, indices.ToArray());

        return (array as TArrayType);
    }

    private static IEnumerable<IEnumerable<int>> CartesianProduct(params int[] dimensions)
    {
        return CartesianProductImpl(Enumerable.Empty<int>(), dimensions);

        IEnumerable<IEnumerable<int>> CartesianProductImpl(
            IEnumerable<int> leftIndices, params int[] dims)
        {
            if (dims.Length == 0)
            {
                yield return leftIndices;
                yield break;
            }

            for (int i = 0; i < dims[0]; i++)
                foreach (var elem in CartesianProductImpl(leftIndices.Concat(new[] { i }),
                         dims.Skip(1).ToArray()))
                    yield return elem;
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.