【问题标题】:What is the shortest way to init a string array with empty strings?用空字符串初始化字符串数组的最短方法是什么?
【发布时间】:2010-11-24 15:32:19
【问题描述】:

令我惊讶

new string[count];

nulls 填充。所以我想出了

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

这是非常冗长的。没有捷径吗?

【问题讨论】:

  • 问题是为什么你需要默认的空字符串?

标签: c# arrays string


【解决方案1】:

你可以使用Enumerable.Repeat:

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

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

【讨论】:

  • 另外值得注意的是,显式创建数组和循环只需要比使用Enumerable.Repeat多几个字符。
【解决方案2】:

处理多个维度

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

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

【讨论】:

    猜你喜欢
    • 2011-09-25
    • 2016-07-27
    • 1970-01-01
    • 2011-12-11
    • 1970-01-01
    • 2018-09-27
    • 2019-12-08
    • 1970-01-01
    相关资源
    最近更新 更多