在C#中将2D数组转换为字符串,寻找最优雅的方式

Convert 2D array to string in C#, looking for most elegant way

我不敢相信没有一种聪明的方法能从二维数组中得到这样的结果,在这种情况下,int[,] a

1
"{1,2,3},{4,5,6},{7,8,9}"

我读过许多类似的问题,并了解到string.Join()只能用于锯齿状阵列(在二维中)。但我不想使用它们,因为初始化比较复杂,而且当我的行(它们的长度都相同)分布在内存中的几个地方时,感觉很糟糕。

这是我的"正常"代码:

1
2
3
4
5
6
7
8
9
10
var s ="";
for (int i = 0; i < a.GetLength(0); i++) {
    if (i > 0) s += ',';
    s += '{';
    for (int j = 0; j < a.GetLength(1); j++) {
        if (j > 0) s += ',';
        s += a[i, j];
    }
    s += '}';
}

这里有一个"高音"的:

1
2
3
4
var s ="{";
var i = 0;
foreach (var item in a) s += (i++ > 0 ? i % a.GetLength(1) == 1 ?"},{" :"," :"") + item;
s += '}';

:)-也不太优雅,可读性也很差。

有什么建议吗?我对Linq开放,因为它不需要太快。我对提高代码的优雅感兴趣,但不仅仅是通过将其移动到扩展方法。


afaik,当我们需要一个对象的字符串时,我们调用的是序列化,所以我更喜欢使用像newtonsoft.json这样的序列化程序:

1
2
var result = $@"{{{JsonConvert.SerializeObject(a)
    .Trim('[', ']').Replace("
[","{").Replace("]","}")}}}";

通过使用与您的解决方案类似的简单for和删除if的方法,这种代码对于小阵列来说更快:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var result = string.Empty;
var maxI = a.GetLength(0);
var maxJ = a.GetLength(1);
for (var i = 0; i < maxI; i++)
{
    result +=",{";
    for (var j = 0; j < maxJ; j++)
    {
        result += $"{a[i, j]},";
    }

    result +="}";
}

result = .Replace(",}","}").Substring(1);

正如建议使用StringBuilder来提高大型阵列的性能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var sb = new StringBuilder(string.Empty);
var maxI = a.GetLength(0);
var maxJ = a.GetLength(1);
for (var i = 0; i < maxI; i++)
{
    sb.Append(",{");
    for (var j = 0; j < maxJ; j++)
    {
        sb.Append($"{a[i, j]},");
    }

    sb.Append("}");
}

sb.Replace(",}","}").Remove(0, 1);
var result = sb.ToString();


LINQ解决方案,而不是性能方面。

1
2
3
4
var str = string.Join(",", a.OfType<int>()
    .Select((value, index) => new {value, index})
    .GroupBy(x => x.index / a.GetLength(1))
    .Select(x => $"{{{string.Join(",", x.Select(y => y.value))}}}"));

注意,在二维数组上不能使用Select,但可以使用OfType,它将返回一个可枚举的二维数组,枚举器将水平穿过二维数组。

x.index / a.GetLength(1)简单地将每个索引除以行的总数。因此,如果您有3行,那么索引将等效地分布在3行中。

最后,对每个组进行字符串联接。

更简单的版本。(分组结果选择器内的格式)

1
2
3
4
var str = string.Join(",", a.OfType<int>()
    .Select((value, index) => new {value, index})
    .GroupBy(x => x.index / a.GetLength(1), x => x.value,
        (i, ints) => $"{{{string.Join(",", ints)}}}"));


考虑这种方法:

1
2
3
4
5
6
7
8
9
10
11
var numbers = new int[,] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };

var results = string.Join(",",
    Enumerable.Range(0, numbers.GetUpperBound(0) + 1)
        .Select(x => Enumerable.Range(0, numbers.GetUpperBound(1) + 1)
            .Select(y => numbers[x, y]))
        .Select(z =>"{" + string.Join(",", z) +"}"));

Console.WriteLine(results);

Console.ReadLine();

它与您的非常相似,但使用LINQ代替。它将二维数组投影到一个Linq可枚举中,然后用大括号将其包装,并在需要时添加逗号。