【问题标题】:Convert 2D array to string in C#, looking for most elegant way在C#中将二维数组转换为字符串,寻找最优雅的方式
【发布时间】:2017-10-08 11:25:36
【问题描述】:

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

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

我已经阅读了许多类似的问题,并了解到string.Join() 只能用于锯齿状数组(二维)。但我不想使用它们,因为初始化更复杂,而且当我的行(长度相同)分布在内存中的多个位置时感觉很糟糕。

这是我的“正常”代码:

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 += '}';
}

这里是“打高尔夫球”的:

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

:) - 也不是很优雅,而且可读性很差。

有什么建议吗?我对 Linq 持开放态度,因为它不必很快。我有兴趣提高代码的优雅性,但不仅仅是将其移至扩展方法。

【问题讨论】:

    标签: c# arrays linq multidimensional-array tostring


    【解决方案1】:

    AFAIK,当我们想要一个对象的字符串时,我们调用的是序列化,所以我更喜欢使用像 Newtonsoft.Json 这样的序列化器:

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

    使用简单的fors 像您的解决方案并删除ifs 的方法可以是 - this code will be faster for small arrays -:

    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 来提高大型数组的性能:

    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();
    

    【讨论】:

      【解决方案2】:

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

      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 行中。

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


      稍微简化一点的版本。 (分组结果选择器内的格式)

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

      【讨论】:

        【解决方案3】:

        考虑这种方法:

        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 可枚举中,然后用大括号将其包裹起来,并在需要的地方添加逗号。

        【讨论】:

          【解决方案4】:

          发布此答案仅供参考,当您不介意以连续方式呈现数据并且边界是静态且始终已知时。

          您可以将字符串输出为纯 csv,使用 LINQ Cast,然后使用 string.Join

          var array = new int[2,3] { { 1, 2, 3 }, { 1, 2, 3 } };
          var output = string.Join(',', array.Cast<int>());
          

          将其解析回来:

          var input = new int[upperLen,lowerLen];
          for (var upper = 0; upper < upperLen; upper++)
              for(var lower = 0; lower < lowerLen; lower++)
                  input[upper, lower] = int.Parse(parsed[(upper * lowerLen) + lower]);
          

          参见示例here

          【讨论】:

          • 这不符合要求或您对它们的解释过于慷慨。这不是要能够将其解析回来,而是要以结构化的方式呈现数据。
          猜你喜欢
          • 1970-01-01
          • 2015-05-14
          • 2022-11-23
          • 1970-01-01
          • 1970-01-01
          • 2016-02-22
          • 2019-01-23
          • 1970-01-01
          • 2019-06-15
          相关资源
          最近更新 更多