Строка разделения в меньшие Строки переменной длины

Я хотел бы разбить Строку определенной переменной длины.
Этому нужно к граничной проверке поэтому, поскольку не взрываются, когда последний раздел строки не пока или дольше, чем длина. Поиск самого сжатого (все же понятный) версия.

Пример:

string x = "AAABBBCC";
string[] arr = x.SplitByLength(3);
// arr[0] -> "AAA";
// arr[1] -> "BBB";
// arr[2] -> "CC"
38
задан John Saunders 9 June 2010 в 21:15
поделиться

9 ответов

Вам необходимо использовать цикл:

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 str, int maxLength) {
    int index = 0;
    while(true) {
        if (index + maxLength >= str.Length) {
            yield return str.Substring(index);
            yield break;
        }
        yield return str.Substring(index, maxLength);
        index += maxLength;
    }
}

2 и альтернатива: (Для тех, кто не может стоять пока (правда) )

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

    yield return str.Substring(index);
}
64
ответ дан 27 November 2019 в 03:17
поделиться

Еще один небольшой вариант (классический, но простой и прагматичный):

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();
    }
}
1
ответ дан 27 November 2019 в 03:17
поделиться
    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();
    }
0
ответ дан 27 November 2019 в 03:17
поделиться

Это не очень лаконично, но я мог бы использовать такой метод расширения:

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

Обратите внимание, что я возвращаю IEnumerable , а не массив. Если вы хотите преобразовать результат в массив, используйте ToArray :

string[] arr = x.SplitByLength(3).ToArray();
6
ответ дан 27 November 2019 в 03:17
поделиться

Использование Batch от MoreLinq, на .Net 4.0:

public static IEnumerable<string> SplitByLength(this string str, int length)
{
    return str.Batch(length, String.Concat);
}

На 3.5 Concat нужен массив, поэтому мы можем использовать Concat с ToArray или, new String:

public static IEnumerable<string> SplitByLength(this string str, int length)
{
    return str.Batch(length, chars => new String(chars.ToArray()));
}

Может быть немного неинтуитивно рассматривать строку как набор символов, поэтому можно предложить манипуляции со строкой.

1
ответ дан 27 November 2019 в 03:17
поделиться

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;
        }
1
ответ дан 27 November 2019 в 03:17
поделиться

Вот что я бы сделал:

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

Этот метод обеспечит отложенное выполнение ( что на самом деле не имеет значения для неизменяемого класса, такого как string , но это стоит отметить).

Затем, если вам нужен метод для заполнения массива, вы могли бы иметь:

public static string[] SplitByLength(this string text, int length) {
    return text.EnumerateByLength(length).ToArray();
}

Причина, по которой я бы выбрал имя EnumerateByLength , а не SplitByLength для " core "метод заключается в том, что string.Split возвращает string [] , поэтому, на мой взгляд, есть приоритет для методов, имена которых начинаются с Split , чтобы возвращать массивы.

Но это только я.

4
ответ дан 27 November 2019 в 03:17
поделиться
    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();
    }
0
ответ дан 27 November 2019 в 03:17
поделиться

Простая для понимания версия:

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

Хотя желательно, чтобы 3 была хорошей константой.

12
ответ дан 27 November 2019 в 03:17
поделиться