Разделенная строка в 512 чанках - PullRequest
10 голосов
/ 27 октября 2009

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

Есть ли хороший способ, например, цикл или так для этого?

Ответы [ 8 ]

20 голосов
/ 27 октября 2009

Примерно так:

private IList<string> SplitIntoChunks(string text, int chunkSize)
{
    List<string> chunks = new List<string>();
    int offset = 0;
    while (offset < text.Length)
    {
        int size = Math.Min(chunkSize, text.Length - offset);
        chunks.Add(text.Substring(offset, size));
        offset += size;
    }
    return chunks;
}

Или просто перебрать:

private IEnumerable<string> SplitIntoChunks(string text, int chunkSize)
{
    int offset = 0;
    while (offset < text.Length)
    {
        int size = Math.Min(chunkSize, text.Length - offset);
        yield return text.Substring(offset, size);
        offset += size;
    }
}

Обратите внимание, что это разбивается на куски кодовых блоков UTF-16, что не совсем то же самое, что деление на куски кодовых точек Unicode, которые, в свою очередь, могут отличаться от разбиения на куски глифов.

3 голосов
/ 27 октября 2009

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

string [] split = Regex.Split(yourString, @"(?<=\G.{512})");

Что это делает? Отрицательный взгляд назад и запоминание последней позиции с \G. Он также поймает последний бит, даже если он не делится на 512.

3 голосов
/ 27 октября 2009

используя реализацию Джона и ключевое слово yield .

IEnumerable<string> Chunks(string text, int chunkSize)
{
    for (int offset = 0; offset < text.Length; offset += chunkSize)
    {
        int size = Math.Min(chunkSize, text.Length - offset);
        yield return text.Substring(offset, size);
    }
}
1 голос
/ 21 мая 2015

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

, поэтому мы должны выполнить цикл хотя бы один раз (на основе кода Джона):

IEnumerable<string> SplitIntoChunks (string text, int chunkSize)
{
    int offset = 0;
    do
    {
        int size = Math.Min (chunkSize, text.Length - offset);
        yield return text.Substring (offset, size);
        offset += size;
    } while (offset < text.Length);
}

или использование for ( Отредактировано : после того, как я немного поигрался с этим, я нашел лучший способ обработать регистр chunkSize больше, чем текст ):

IEnumerable<string> SplitIntoChunks (string text, int chunkSize)
{
    if (text.Length <= chunkSize)
        yield return text;
    else
    {
        var chunkCount = text.Length / chunkSize;
        var remainingSize = text.Length % chunkSize;

        for (var offset = 0; offset < chunkCount; ++offset)
            yield return text.Substring (offset * chunkSize, chunkSize);

        // yield remaining text if any
        if (remainingSize != 0)
            yield return text.Substring (chunkCount * chunkSize, remainingSize);
    }
}

Это также можно использовать с циклом do / while;)

1 голос
/ 27 октября 2009

Я позволю себе предоставить более LINQified версию решения Джона, основанную на том факте, что тип string реализует IEnumerable<char>:

private IList<string> SplitIntoChunks(string text, int chunkSize)
{
    var chunks = new List<string>();
    int offset = 0;
    while(offset < text.Length) {
        chunks.Add(new string(text.Skip(offset).Take(chunkSize).ToArray()));
        offset += chunkSize;
    }
    return chunks;
}
1 голос
/ 27 октября 2009
static IEnumerable<string> Split(string str, int chunkSize)    
{   
    int len = str.Length;
    return Enumerable.Range(0, len / chunkSize).Select(i => str.Substring(i * chunkSize, chunkSize));    
}

source: Разделение строки на куски определенного размера

0 голосов
/ 08 сентября 2017

Общий метод расширения:

using System;
using System.Collections.Generic;
using System.Linq;

public static class IEnumerableExtensions
{
  public static IEnumerable<IEnumerable<T>> SplitToChunks<T> (this IEnumerable<T> coll, int chunkSize)
  {
    int skipCount = 0;
    while (coll.Skip (skipCount).Take (chunkSize) is IEnumerable<T> part && part.Any ())
    {
      skipCount += chunkSize;
      yield return part;
    }
  }
}

class Program
{
  static void Main (string[] args)
  {
    var col = Enumerable.Range(1,1<<10);
    var chunks = col.SplitToChunks(8);

    foreach (var c in chunks.Take (200))
    {
      Console.WriteLine (string.Join (" ", c.Select (n => n.ToString ("X4"))));
    }

    Console.WriteLine ();
    Console.WriteLine ();

    "Split this text into parts that are fifteen characters in length, surrounding each part with single quotes and output each into the console on seperate lines."
      .SplitToChunks (15)
      .Select(p => $"'{string.Concat(p)}'")
      .ToList ()
      .ForEach (p => Console.WriteLine (p));

    Console.ReadLine ();
  }
}
0 голосов
/ 27 октября 2009

Что-то вроде?

Calculate eachLength = StringLength / WantedCharLength
Then for (int i = 0; i < StringLength; i += eachLength)
SubString (i, eachLength);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...