Splitting a string into chunks of a certain size

后端 未结 30 1543
时光说笑
时光说笑 2020-11-22 07:55

Suppose I had a string:

string str = \"1111222233334444\"; 

How can I break this string into chunks of some size?

e.g., breaking t

相关标签:
30条回答
  • 2020-11-22 08:00

    I've slightly build up on João's solution. What I've done differently is in my method you can actually specify whether you want to return the array with remaining characters or whether you want to truncate them if the end characters do not match your required chunk length, I think it's pretty flexible and the code is fairly straight forward:

    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;
            }     
        }
    }
    
    0 讨论(0)
  • 2020-11-22 08:01

    I recently had to write something that accomplishes this at work, so I thought I would post my solution to this problem. As an added bonus, the functionality of this solution provides a way to split the string in the opposite direction and it does correctly handle unicode characters as previously mentioned by Marvin Pinto above. So, here it is:

    using System;
    using Extensions;
    
    namespace TestCSharp
    {
        class Program
        {
            static void Main(string[] args)
            {    
                string asciiStr = "This is a string.";
                string unicodeStr = "これは文字列です。";
    
                string[] array1 = asciiStr.Split(4);
                string[] array2 = asciiStr.Split(-4);
    
                string[] array3 = asciiStr.Split(7);
                string[] array4 = asciiStr.Split(-7);
    
                string[] array5 = unicodeStr.Split(5);
                string[] array6 = unicodeStr.Split(-5);
            }
        }
    }
    
    namespace Extensions
    {
        public static class StringExtensions
        {
            /// <summary>Returns a string array that contains the substrings in this string that are seperated a given fixed length.</summary>
            /// <param name="s">This string object.</param>
            /// <param name="length">Size of each substring.
            ///     <para>CASE: length &gt; 0 , RESULT: String is split from left to right.</para>
            ///     <para>CASE: length == 0 , RESULT: String is returned as the only entry in the array.</para>
            ///     <para>CASE: length &lt; 0 , RESULT: String is split from right to left.</para>
            /// </param>
            /// <returns>String array that has been split into substrings of equal length.</returns>
            /// <example>
            ///     <code>
            ///         string s = "1234567890";
            ///         string[] a = s.Split(4); // a == { "1234", "5678", "90" }
            ///     </code>
            /// </example>            
            public static string[] Split(this string s, int length)
            {
                System.Globalization.StringInfo str = new System.Globalization.StringInfo(s);
    
                int lengthAbs = Math.Abs(length);
    
                if (str == null || str.LengthInTextElements == 0 || lengthAbs == 0 || str.LengthInTextElements <= lengthAbs)
                    return new string[] { str.ToString() };
    
                string[] array = new string[(str.LengthInTextElements % lengthAbs == 0 ? str.LengthInTextElements / lengthAbs: (str.LengthInTextElements / lengthAbs) + 1)];
    
                if (length > 0)
                    for (int iStr = 0, iArray = 0; iStr < str.LengthInTextElements && iArray < array.Length; iStr += lengthAbs, iArray++)
                        array[iArray] = str.SubstringByTextElements(iStr, (str.LengthInTextElements - iStr < lengthAbs ? str.LengthInTextElements - iStr : lengthAbs));
                else // if (length < 0)
                    for (int iStr = str.LengthInTextElements - 1, iArray = array.Length - 1; iStr >= 0 && iArray >= 0; iStr -= lengthAbs, iArray--)
                        array[iArray] = str.SubstringByTextElements((iStr - lengthAbs < 0 ? 0 : iStr - lengthAbs + 1), (iStr - lengthAbs < 0 ? iStr + 1 : lengthAbs));
    
                return array;
            }
        }
    }
    

    Also, here is an image link to the results of running this code: http://i.imgur.com/16Iih.png

    0 讨论(0)
  • 2020-11-22 08:01

    I know question is years old, but here is a Rx implementation. It handles the length % chunkSize != 0 problem out of the box:

       public static IEnumerable<string> Chunkify(this string input, int size)
            {
                if(size < 1)
                    throw new ArgumentException("size must be greater than 0");
    
                return input.ToCharArray()
                    .ToObservable()
                    .Buffer(size)            
                    .Select(x => new string(x.ToArray()))
                    .ToEnumerable();
            }
    
    0 讨论(0)
  • 2020-11-22 08:04

    Based around other posters answers, along with some samples of useage:

    public static string FormatSortCode(string sortCode)
    {
        return ChunkString(sortCode, 2, "-");
    }
    public static string FormatIBAN(string iban)
    {
        return ChunkString(iban, 4, "&nbsp;&nbsp;");
    }
    
    private static string ChunkString(string str, int chunkSize, string separator)
    {
        var b = new StringBuilder();
        var stringLength = str.Length;
        for (var i = 0; i < stringLength; i += chunkSize)
        {
            if (i + chunkSize > stringLength) chunkSize = stringLength - i;
            b.Append(str.Substring(i, chunkSize));
            if (i+chunkSize != stringLength)
                b.Append(separator);
        }
        return b.ToString();
    }
    
    0 讨论(0)
  • 2020-11-22 08:06

    I think this is an straight forward answer:

    public static IEnumerable<string> Split(this string str, int chunkSize)
        {
            if(string.IsNullOrEmpty(str) || chunkSize<1)
                throw new ArgumentException("String can not be null or empty and chunk size should be greater than zero.");
            var chunkCount = str.Length / chunkSize + (str.Length % chunkSize != 0 ? 1 : 0);
            for (var i = 0; i < chunkCount; i++)
            {
                var startIndex = i * chunkSize;
                if (startIndex + chunkSize >= str.Length)
                    yield return str.Substring(startIndex);
                else
                    yield return str.Substring(startIndex, chunkSize);
            }
        }
    

    And it covers edge cases.

    0 讨论(0)
  • 2020-11-22 08:08

    You can use morelinq by Jon Skeet. Use Batch like:

    string str = "1111222233334444";
    int chunkSize = 4;
    var chunks = str.Batch(chunkSize).Select(r => new String(r.ToArray()));
    

    This will return 4 chunks for the string "1111222233334444". If the string length is less than or equal to the chunk size Batch will return the string as the only element of IEnumerable<string>

    For output:

    foreach (var chunk in chunks)
    {
        Console.WriteLine(chunk);
    }
    

    and it will give:

    1111
    2222
    3333
    4444
    
    0 讨论(0)
提交回复
热议问题