Возможно, основной вопрос, но скажем, что у меня есть строка длиной 2000 символов, мне нужно разбить эту строку на максимальные 512 символов.
Есть ли хороший способ, например, цикл или так для этого?
Возможно, основной вопрос, но скажем, что у меня есть строка длиной 2000 символов, мне нужно разбить эту строку на максимальные 512 символов.
Есть ли хороший способ, например, цикл или так для этого?
Что-то вроде этого:
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, что, в свою очередь, может быть не таким, как разбиение на куски глифов.
используя реализацию Jon и ключевое слово 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);
}
}
Хотя этот вопрос между тем имеет принятый ответ, здесь короткая версия с помощью регулярных выражений. Пуристам может не нравиться это (понятно), но когда вам нужно быстрое решение, и вам удобно с регулярными выражениями, это может быть и так. Производительность довольно хороша, удивительно:
string [] split = Regex.Split(yourString, @"(?<=\G.{512})");
Что он делает? Отрицательный внешний вид и запоминание последней позиции с помощью \G
. Он также поймает последний бит, даже если он не делится на 512.
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));
}
Я осмелюсь предоставить более LINQified версию решения Jon, основанную на том, что тип 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;
}
Большая часть ответа может иметь тот же недостаток. Учитывая пустой текст, они ничего не принесут. Мы (I) ожидаем, что, по крайней мере, вернем эту пустую строку (такое же поведение, как разделение на char не в строке, что даст один элемент: данная строка)
поэтому мы должны зацикливаться хотя бы один раз все время (на основе кода Джона):
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 (Edited): после того, как он немного поработал с этим, я нашел лучший способ обработать случай 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;)
Общий метод расширения:
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 ();
}
}
Что-то вроде?
Calculate eachLength = StringLength / WantedCharLength
Then for (int i = 0; i < StringLength; i += eachLength)
SubString (i, eachLength);