【问题标题】:How to split a string into an array of two letter substrings with C#如何使用 C# 将字符串拆分为两个字母子字符串的数组
【发布时间】:2021-11-15 22:07:48
【问题描述】:

问题

给定一个示例字符串abcdef,我试图将其拆分为一个由两个字符串元素组成的数组,结果应该是['ab','cd','ef']

我尝试了什么

我尝试遍历字符串,同时将子字符串存储在我在方法内声明的数组中的当前索引中,但我得到了这个输出 ['ab','bc','cd','de','ef']

我使用的代码

static string[] mymethod(string str)
{
    string[] r= new string[str.Length];
    for(int i=0; i<str.Length-1; i++)
    {
        r[i]=str.Substring(i,2);
    }
    return r;
}

非常欢迎任何使用代码纠正该问题以返回正确输出的解决方案,谢谢

【问题讨论】:

  • 在您的解决方案中,i 看起来不会以相同长度的子字符串移动。始终以 1 而不是 2 递增(您想要成为“截止” ' 每个分组的点数)
  • @马克。 C,好的,更改代码中的增量变量,将返回反馈
  • 您确实意识到您请求的输出中有一半的“r”数组将为空?
  • 非常感谢
  • @Hans Kestling,我按照建议实施了更正,代码运行良好

标签: c# arrays string


【解决方案1】:

您的问题是您每次都将索引增加 1 而不是 2

 var res = new List<string>();
 for (int i = 0; i < x.Length - 1; i += 2)
 {
     res.Add(x.Substring(i, 2));
 }

应该有效

编辑: 因为您要求默认 _ 后缀以防奇数字符数量, 这应该是变化:

  var testString = "odd";
  string workOn = testString.Length % 2 != 0
     ? testString + "_"
     : testString;
  var res = new List<string>();
  for (int i = 0; i < workOn.Length - 1; i += 2)
  {
      res.Add(workOn.Substring(i, 2));
  }

需要注意的两个注意事项:

  • .NET 6 Chunk() 可用,因此您可以按照其他答案中的建议使用它
  • 如果输入很长,此解决方案可能不是最好的 所以这真的取决于你的意见和期望是什么

【讨论】:

  • r 应该是原始字符串长度的一半(因为每个索引包含 2 个字符)。这也会抛出奇数字符串长度的异常。
  • @JohnathanBarclay,输入有一个包含两个字符的数组,
  • @JohnathanBarclay,你运行了吗?它不会抛出任何东西dotnetfiddle.net/YBhzZ1
  • 好的,它会丢弃最后一个字符而不是抛出异常。
  • 这通过了我能想到的所有测试用例,谢谢 Dor,我将 ti 标记为已接受,我刚刚添加了res.ToArray(),它按预期返回了。祝您编码愉快:))
【解决方案2】:

使用 linq 可以通过以下方式实现:

char[] word = "abcdefg".ToCharArray();
var evenCharacters = word.Where((_, idx) => idx % 2 == 0);
var oddCharacters = word.Where((_, idx) => idx % 2 == 1);
var twoCharacterLongSplits = evenCharacters
    .Zip(oddCharacters)
    .Select((pair) => new char[] { pair.First, pair.Second });

诀窍如下,我们创建了两个集合:

  • 我们只有那些原始索引为 even (% 2 == 0) 的字符
  • 我们只有那些原始索引为奇数的字符 (% 2 == 1)

然后我们压缩它们。因此,我们通过从偶数集合中获取一项和从奇数集合中获取一项来创建一个元组。然后我们通过从偶数中取出一个项目来创建一个新的元组......

最后我们将元组转换为数组以获得所需的输出格式。

【讨论】:

    【解决方案3】:

    如果您使用的是最新的.NET 版本,即(.NET 6.0 RC 1),那么您可以尝试Chunk() 方法,

    var strChunks = "abcdef".Chunk(2); //[['a', 'b'], ['c', 'd'], ['e', 'f']]
    
    var result = strChunks.Select(x => string.Join('', x)).ToArray(); //["ab", "cd", "ef"]
    

    注意:由于 .NET 的最新版本,我无法在 fiddle 或我的本地机器上进行测试

    【讨论】:

    • 谁能指点我任何支持6.0 RC 1C#版本的C#小提琴
    • 请注意ToCharArray 是不必要的,因为string 无论如何都会实现IEnumerable&lt;char&gt;
    • @PrasadTelkikar,很遗憾目前没有
    • 啊该死,我太慢了 :) 好答案。
    • @PeterCsala,是的,我更新了我的答案。谢谢指正
    【解决方案4】:

    .net 6 有一个 IEnumerable.Chunk() 方法,您可以使用它来执行此操作,如下所示:

    public static void Main()
    {
        string[] result = 
           "abcdef"
           .Chunk(2)
           .Select(chunk => new string(chunk)).ToArray();
    
        Console.WriteLine(string.Join(", ", result)); // Prints "ab, cd, ef"
    }
    

    在.net 6 之前,您可以使用MoreLinq.Batch() 来做同样的事情。


    [编辑]响应以下请求:

    MoreLinq 是一组 Linq 实用程序,最初由 Jon Skeet 编写。您可以通过转到 Project | Manage NuGet Packages 然后浏览 MoreLinq 并安装它来找到一个实现。

    安装后,添加using MoreLinq.Extensions;,然后你就可以像这样使用MoreLinq.Batch扩展了:

    public static void Main()
    {
        string[] result = "abcdef"
           .Batch(2)
           .Select(chunk => new string(chunk.ToArray())).ToArray();
    
        Console.WriteLine(string.Join(", ", result)); // Prints "ab, cd, ef"
    }
    

    请注意,没有接受IEnumerable&lt;char&gt; 的字符串构造函数,因此需要上面的chunk.ToArray()

    不过,我要说的是,仅将整个 MoreLinq 包含在一种扩展方法中可能是矫枉过正。你可以为Enumerable.Chunk()写你自己的扩展方法:

    public static class MyBatch
    {
        public static IEnumerable<T[]> Chunk<T>(this IEnumerable<T> self, int size)
        {
            T[] bucket = null;
            int count  = 0;
    
            foreach (var item in self)
            {
                if (bucket == null)
                    bucket = new T[size];
    
                bucket[count++] = item;
    
                if (count != size)
                    continue;
    
                yield return bucket;
    
                bucket = null;
                count  = 0;
            }
    
            if (bucket != null && count > 0)
                yield return bucket.Take(count).ToArray();
        }
    }
    

    【讨论】:

    • 你能详细说明一下 MoreLinq.Batch() 因为我碰巧没有那个版本的 C#
    • morelinq 不是 .Net Framework 的一部分,而是可以在项目中使用的附加开源库
    【解决方案5】:

    您在正确的轨道上,但您需要增加 2 而不是 1。您还需要在获取第二个字符之前检查数组是否尚未结束,否则您可能会遇到索引越界异常。试试我在下面写的这段代码。我已经尝试过了,它有效。最好的!

    public static List<string> splitstring(string str)
            {
                List<string> result = new List<string>();
                int strlen = str.Length;
                for(int i = 0; i<strlen; i+=2)
                {
                    string currentstr = str[i].ToString();
                    if (i + 1 <= strlen-1)
                    { currentstr += str[i + 1].ToString(); }
                    result.Add(currentstr);
                }
                return result;
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-07
      • 1970-01-01
      • 2012-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多