假设我有一个字符串:

string str = "1111222233334444"; 

我如何把这个字符串分成一定大小的块?

例如,将它分解为4的大小将返回字符串:

"1111"
"2222"
"3333"
"4444"

当前回答

六年后o_O

仅仅因为

    public static IEnumerable<string> Split(this string str, int chunkSize, bool remainingInFront)
    {
        var count = (int) Math.Ceiling(str.Length/(double) chunkSize);
        Func<int, int> start = index => remainingInFront ? str.Length - (count - index)*chunkSize : index*chunkSize;
        Func<int, int> end = index => Math.Min(str.Length - Math.Max(start(index), 0), Math.Min(start(index) + chunkSize - Math.Max(start(index), 0), chunkSize));
        return Enumerable.Range(0, count).Select(i => str.Substring(Math.Max(start(i), 0),end(i)));
    }

or

    private static Func<bool, int, int, int, int, int> start = (remainingInFront, length, count, index, size) =>
        remainingInFront ? length - (count - index) * size : index * size;

    private static Func<bool, int, int, int, int, int, int> end = (remainingInFront, length, count, index, size, start) =>
        Math.Min(length - Math.Max(start, 0), Math.Min(start + size - Math.Max(start, 0), size));

    public static IEnumerable<string> Split(this string str, int chunkSize, bool remainingInFront)
    {
        var count = (int)Math.Ceiling(str.Length / (double)chunkSize);
        return Enumerable.Range(0, count).Select(i => str.Substring(
            Math.Max(start(remainingInFront, str.Length, count, i, chunkSize), 0),
            end(remainingInFront, str.Length, count, i, chunkSize, start(remainingInFront, str.Length, count, i, chunkSize))
        ));
    }

AFAIK所有的边缘情况都处理好了。

Console.WriteLine(string.Join(" ", "abc".Split(2, false))); // ab c
Console.WriteLine(string.Join(" ", "abc".Split(2, true))); // a bc
Console.WriteLine(string.Join(" ", "a".Split(2, true))); // a
Console.WriteLine(string.Join(" ", "a".Split(2, false))); // a

其他回答

稍微更改为返回大小不等于chunkSize的部件

public static IEnumerable<string> Split(this string str, int chunkSize)
    {
        var splits = new List<string>();
        if (str.Length < chunkSize) { chunkSize = str.Length; }
        splits.AddRange(Enumerable.Range(0, str.Length / chunkSize).Select(i => str.Substring(i * chunkSize, chunkSize)));
        splits.Add(str.Length % chunkSize > 0 ? str.Substring((str.Length / chunkSize) * chunkSize, str.Length - ((str.Length / chunkSize) * chunkSize)) : string.Empty);
        return (IEnumerable<string>)splits;
    }

我在João的解决方案基础上做了一些改进。 我所做的不同之处在于,在我的方法中,你实际上可以指定是否要返回带有剩余字符的数组,或者如果结束字符不匹配所需的块长度,你是否要截断它们,我认为这是相当灵活的,代码相当直接:

using System;
using System.Linq;
using System.Text.RegularExpressions;

namespace SplitFunction
{
    class Program
    {
        static void Main(string[] args)
        {
            string text = "hello, how are you doing today?";
            string[] chunks = SplitIntoChunks(text, 3,false);
            if (chunks != null)
            {
                chunks.ToList().ForEach(e => Console.WriteLine(e));
            }

            Console.ReadKey();
        }

        private static string[] SplitIntoChunks(string text, int chunkSize, bool truncateRemaining)
        {
            string chunk = chunkSize.ToString(); 
            string pattern = truncateRemaining ? ".{" + chunk + "}" : ".{1," + chunk + "}";

            string[] chunks = null;
            if (chunkSize > 0 && !String.IsNullOrEmpty(text))
                chunks = (from Match m in Regex.Matches(text,pattern)select m.Value).ToArray(); 

            return chunks;
        }     
    }
}

这样写一行代码怎么样?

List<string> result = new List<string>(Regex.Split(target, @"(?<=\G.{4})", RegexOptions.Singleline));

对于这个正则表达式,最后一个块是否小于4个字符并不重要,因为它只查看它后面的字符。

我知道这不是最有效的解决方案,但我不得不把它扔出去。

以下是我的观点:

  IEnumerable<string> Split(string str, int chunkSize)
  {
     while (!string.IsNullOrWhiteSpace(str))
     {
        var chunk = str.Take(chunkSize).ToArray();
        str = str.Substring(chunk.Length);
        yield return new string(chunk);

     }

  }//Split

我把它提升到了另一个层次。扔掉是一个简单的句子,但在我的情况下,我需要整个单词。我想我应该把它发布出来,以防有人需要类似的东西。

static IEnumerable<string> Split(string orgString, int chunkSize, bool wholeWords = true)
{
    if (wholeWords)
    {
        List<string> result = new List<string>();
        StringBuilder sb = new StringBuilder();

        if (orgString.Length > chunkSize)
        {
            string[] newSplit = orgString.Split(' ');
            foreach (string str in newSplit)
            {
                if (sb.Length != 0)
                    sb.Append(" ");

                if (sb.Length + str.Length > chunkSize)
                {
                    result.Add(sb.ToString());
                    sb.Clear();
                }

                sb.Append(str);
            }

            result.Add(sb.ToString());
        }
        else
            result.Add(orgString);

        return result;
    }
    else
        return new List<string>(Regex.Split(orgString, @"(?<=\G.{" + chunkSize + "})", RegexOptions.Singleline));
}

基于以下评论的结果:

string msg = "336699AABBCCDDEEFF";
foreach (string newMsg in Split(msg, 2, false))
{
    Console.WriteLine($">>{newMsg}<<");
}

Console.ReadKey();

结果:

>>33<<
>>66<<
>>99<<
>>AA<<
>>BB<<
>>CC<<
>>DD<<
>>EE<<
>>FF<<
>><<

另一种说法是:

List<string> splitData = (List<string>)Split(msg, 2, false);

for (int i = 0; i < splitData.Count - 1; i++)
{
    Console.WriteLine($">>{splitData[i]}<<");
}

Console.ReadKey();

新结果:

>>33<<
>>66<<
>>99<<
>>AA<<
>>BB<<
>>CC<<
>>DD<<
>>EE<<
>>FF<<