C# 按长度变量将字符串拆分为较小的字符串

C# 按长度变量将字符串拆分为较小的字符串,c#,.net,algorithm,string,C#,.net,Algorithm,String,我想用一个特定的长度变量来分隔字符串。 它需要进行边界检查,以便在字符串的最后一段不等于或长于长度时不会爆炸。寻找最简洁(但也可以理解)的版本 例如: string x = "AAABBBCC"; string[] arr = x.SplitByLength(3); // arr[0] -> "AAA"; // arr[1] -> "BBB"; // arr[2] -> "CC" 易于理解的版本: string x = "AAABBBCC"; List<string&g

我想用一个特定的长度变量来分隔字符串。
它需要进行边界检查,以便在字符串的最后一段不等于或长于长度时不会爆炸。寻找最简洁(但也可以理解)的版本

例如:

string x = "AAABBBCC";
string[] arr = x.SplitByLength(3);
// arr[0] -> "AAA";
// arr[1] -> "BBB";
// arr[2] -> "CC"

易于理解的版本:

string x = "AAABBBCC";
List<string> a = new List<string>();
for (int i = 0; i < x.Length; i += 3)
{
    if((i + 3) < x.Length)
        a.Add(x.Substring(i, 3));
    else
        a.Add(x.Substring(i));
}
string x=“aaabbcc”;
列表a=新列表();
对于(int i=0;i

尽管3最好是一个很好的常数。

您需要使用一个循环:

public static IEnumerable<string> SplitByLength(this string str, int maxLength) {
    for (int index = 0; index < str.Length; index += maxLength) {
        yield return str.Substring(index, Math.Min(maxLength, str.Length - index));
    }
}

它不是特别简洁,但我可以使用如下扩展方法:

public static IEnumerable<string> SplitByLength(this string s, int length)
{
    for (int i = 0; i < s.Length; i += length)
    {
        if (i + length <= s.Length)
        {
            yield return s.Substring(i, length);
        }
        else
        {
            yield return s.Substring(i);
        }
    }
}
下面是我要做的:

public static IEnumerable<string> EnumerateByLength(this string text, int length) {
    int index = 0;
    while (index < text.Length) {
        int charCount = Math.Min(length, text.Length - index);
        yield return text.Substring(index, charCount);
        index += length;
    }
}
对于“核心”方法,我之所以选择名称
EnumerateBylLength
而不是
SplitBylLength
,是因为
string.Split
返回一个
string[]
,因此在我看来,名称以
Split
开头的方法返回数组具有优先权

不过,这只是我的问题。

使用.Net 4.0上的from:

public static IEnumerable<string> SplitByLength(this string str, int length)
{
    return str.Batch(length, String.Concat);
}
将字符串视为字符集合可能有点不直观,因此可能会提供字符串操作。

private string[]SplitByLength(字符串s,int d)
    private string[] SplitByLength(string s, int d)
    {
        List<string> stringList = new List<string>();
        if (s.Length <= d) stringList.Add(s);
        else
        {
            int x = 0;
            for (; (x + d) < s.Length; x += d)
            {
                stringList.Add(s.Substring(x, d));
            }
            stringList.Add(s.Substring(x));
        }
        return stringList.ToArray();
    }
{ List stringList=新列表(); 如果(s.Length
private void按钮2\u单击(对象发送者,事件参数e)
{
字符串s=“aaabbccc”;
字符串[]a=SplitByLenght(s,3);
}
私有字符串[]SplitByLenght(字符串s,int split)
{
//喜欢使用列表,因为我可以添加到列表中
列表=新列表();
//整数除法
int TimesThroughTheLoop=s.Length/split;
for(int i=0;i
UPD:使用一些Linq使它实际上简洁


static IEnumerable EnumerateByLength(string str, int len)
        {
            Match m = (new Regex(string.Format("^(.{{1,{0}}})*$", len))).Match(str);
            if (m.Groups.Count <= 1)
                return Empty;
            return (from Capture c in m.Groups[1].Captures select c.Value);
        }
初始版本:


        static string[] Empty = new string [] {};

        static string[] SplitByLength(string str, int len)
        {
            Regex r = new Regex(string.Format("^(.{{1,{0}}})*$",len));
            Match m = r.Match(str);
            if(m.Groups.Count <= 1)
                return Empty;

            string [] result = new string[m.Groups[1].Captures.Count];
            int ix = 0;
            foreach(Capture c in m.Groups[1].Captures)
            {
                result[ix++] = c.Value;
            }
            return result;
        }

还有一个细微的变化(经典但简单实用):

类程序
{
静态void Main(字符串[]参数){
字符串msg=“aaabbcc”;
string[]test=msg.SplitByLength(3);
}
}
公共静态类SplitStringByLength
{
公共静态字符串[]SplitByLength(此字符串为inputString,int segmentSize){
列表段=新列表();
int whistegmentcount=inputString.Length/segmentSize;
int i;
对于(i=0;i
我的解决方案:

public static string[] SplitToChunks(this string source, int maxLength)
{
    return source
        .Where((x, i) => i % maxLength == 0)
        .Select(
            (x, i) => new string(source
                .Skip(i * maxLength)
                .Take(maxLength)
                .ToArray()))
        .ToArray();
}

实际上,我宁愿使用
List
而不是
string[]

我遇到了一个奇怪的场景,我先分割了一个字符串,然后在连接它们之前重新排列了段(即反转),然后我需要反转分段。下面是对以下内容的更新:

//
///将给定字符串拆分为大小相等的段(如果不均匀分割,则可能使用“余数”)。可以选择首先返回“余数”。
/// 
///源字符串
///每个段的大小(剩余部分除外,剩余部分较小)
///如果分割成段会导致最后的块比左边小,那么从一开始就开始
///内的段列表
///原始方法https://stackoverflow.com/questions/3008718/split-string-into-smaller-strings-by-length-variable 
私有静态IEnumerable-ToSegments(字符串str,int-maxLength,bool-remainderFirst=false){
//注意:`maxLength==0`不仅没有意义,而且会导致无限循环
如果(maxLength<1)抛出新ArgumentOutOfRangeException(“maxLength”,maxLength,“应该大于0”);
//对于由“remainderFirst==true”的无意义请求和无余数(`maxLength==1`或偶数除法)引起的无限循环正确
如果(remainderFirst&&str.Length%maxLength==0)remainderFirst=false;
var指数=0;
//请注意,我们希望在到达终点之前停止
//因为如果准确的话,我们最终会有一个
//空段
而(索引+最大长度
(我还纠正了原始
版本中的一个错误,如果
maxLength==1
,则会导致空段)

我有一个递归解决方案:
公共列表拆分数组(字符串项,整数大小)
{

如果(item.Length如果要拆分的int大于字符串长度,这将不会产生任何结果。@JYelton:不,它仍然会进入循环并在else语句中结束。@JYelton:我想你错了。你是说有什么方法可以在不触发任何一个的情况下溜过
If
/
else
n、 我最初认为,如果拆分长度大于字符串长度,循环将不会执行,但检查机制是内置的
public static IEnumerable<string> SplitByLength(this string str, int length)
{
    return str.Batch(length, chars => new String(chars.ToArray()));
}
    private string[] SplitByLength(string s, int d)
    {
        List<string> stringList = new List<string>();
        if (s.Length <= d) stringList.Add(s);
        else
        {
            int x = 0;
            for (; (x + d) < s.Length; x += d)
            {
                stringList.Add(s.Substring(x, d));
            }
            stringList.Add(s.Substring(x));
        }
        return stringList.ToArray();
    }
    private void button2_Click(object sender, EventArgs e)
    {
        string s = "AAABBBCCC";
        string[] a = SplitByLenght(s,3);
    }

    private string[] SplitByLenght(string s, int split)
    {
        //Like using List because I can just add to it 
        List<string> list = new List<string>();

                    // Integer Division
        int TimesThroughTheLoop = s.Length/split;


        for (int i = 0; i < TimesThroughTheLoop; i++)
        {
            list.Add(s.Substring(i * split, split));

        }

        // Pickup the end of the string
        if (TimesThroughTheLoop * split != s.Length)
        {
            list.Add(s.Substring(TimesThroughTheLoop * split));
        }

        return list.ToArray();
    }

static IEnumerable EnumerateByLength(string str, int len)
        {
            Match m = (new Regex(string.Format("^(.{{1,{0}}})*$", len))).Match(str);
            if (m.Groups.Count <= 1)
                return Empty;
            return (from Capture c in m.Groups[1].Captures select c.Value);
        }

        static string[] Empty = new string [] {};

        static string[] SplitByLength(string str, int len)
        {
            Regex r = new Regex(string.Format("^(.{{1,{0}}})*$",len));
            Match m = r.Match(str);
            if(m.Groups.Count <= 1)
                return Empty;

            string [] result = new string[m.Groups[1].Captures.Count];
            int ix = 0;
            foreach(Capture c in m.Groups[1].Captures)
            {
                result[ix++] = c.Value;
            }
            return result;
        }
class Program
{
    static void Main(string[] args) {
        string msg = "AAABBBCC";

        string[] test = msg.SplitByLength(3);            
    }
}

public static class SplitStringByLength
{
    public static string[] SplitByLength(this string inputString, int segmentSize) {
        List<string> segments = new List<string>();

        int wholeSegmentCount = inputString.Length / segmentSize;

        int i;
        for (i = 0; i < wholeSegmentCount; i++) {
            segments.Add(inputString.Substring(i * segmentSize, segmentSize));
        }

        if (inputString.Length % segmentSize != 0) {
            segments.Add(inputString.Substring(i * segmentSize, inputString.Length - i * segmentSize));
        }

        return segments.ToArray();
    }
}
public static string[] SplitToChunks(this string source, int maxLength)
{
    return source
        .Where((x, i) => i % maxLength == 0)
        .Select(
            (x, i) => new string(source
                .Skip(i * maxLength)
                .Take(maxLength)
                .ToArray()))
        .ToArray();
}
    /// <summary>
    /// Split the given string into equally-sized segments (possibly with a 'remainder' if uneven division).  Optionally return the 'remainder' first.
    /// </summary>
    /// <param name="str">source string</param>
    /// <param name="maxLength">size of each segment (except the remainder, which will be less)</param>
    /// <param name="remainderFirst">if dividing <paramref name="str"/> into segments would result in a chunk smaller than <paramref name="maxLength"/> left at the end, instead take it from the beginning</param>
    /// <returns>list of segments within <paramref name="str"/></returns>
    /// <remarks>Original method at https://stackoverflow.com/questions/3008718/split-string-into-smaller-strings-by-length-variable </remarks>
    private static IEnumerable<string> ToSegments(string str, int maxLength, bool remainderFirst = false) {
        // note: `maxLength == 0` would not only not make sense, but would result in an infinite loop
        if(maxLength < 1) throw new ArgumentOutOfRangeException("maxLength", maxLength, "Should be greater than 0");
        // correct for the infinite loop caused by a nonsensical request of `remainderFirst == true` and no remainder (`maxLength==1` or even division)
        if( remainderFirst && str.Length % maxLength == 0 ) remainderFirst = false;

        var index = 0;
        // note that we want to stop BEFORE we reach the end
        // because if it's exact we'll end up with an
        // empty segment
        while (index + maxLength < str.Length)
        {
            // do we want the 'final chunk' first or at the end?
            if( remainderFirst && index == 0 ) {
                // figure out remainder size
                var remainder = str.Length % maxLength;
                yield return str.Substring(index, remainder);

                index += remainder;
            }
            // normal stepthrough
            else {
                yield return str.Substring(index, maxLength);
                index += maxLength;
            }
        }

        yield return str.Substring(index);
    }//---  fn  ToSegments
    public List<string> SplitArray(string item, int size)
    {
        if (item.Length <= size) return new List<string> { item };
        var temp = new List<string> { item.Substring(0,size) };
        temp.AddRange(SplitArray(item.Substring(size), size));
        return temp;
    }