使用空字符串初始化字符串数组的最短方法是什么?

时间:2010-11-24 15:32:20

标签: c# arrays string

令我惊讶的是

new string[count];

填充了null s。所以我想出了

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

非常冗长。没有shorcut?

2 个答案:

答案 0 :(得分:36)

您可以使用Enumerable.Repeat

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

(但请注意,创建正确大小和循环的字符串数组会提供更好的性能。)

答案 1 :(得分:1)

处理多个维度

我不得不使用一堆必须初始化为空的字符串数组,有些是多维的。这有点痛苦,所以我创建了以下有用的内容:

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

然后你可以做类似的事情:

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

更新 - 处理任意维度的一种方法

我认为使用通用方法尝试概括它以组合创建数组并初始化它会很有趣。它不会像上面那样快,但它会处理任意数量的维度:

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 would create a string[2,3,4,2] initialized with empty strings
ArrayFactory.CreateArrayInitializedWithEmptyStrings<string[,,,]>(2,3,4,2);

向Ian Griffiths道明他的article series,这是广义CartesianProduct方法的来源。

更新2

这是笛卡尔积的精炼版,使用递归来获取索引组合:

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