문자열이 있다고 가정합니다.
string str = "1111222233334444";
이 문자열을 어떤 크기의 덩어리로 나눌 수 있습니까?
예를 들어 이것을 4 크기로 나누면 문자열이 반환됩니다.
"1111"
"2222"
"3333"
"4444"
답변
static IEnumerable<string> Split(string str, int chunkSize)
{
return Enumerable.Range(0, str.Length / chunkSize)
.Select(i => str.Substring(i * chunkSize, chunkSize));
}
엣지 케이스 ( null
또는 빈 입력 문자열 chunkSize == 0
, 입력 문자열 길이를 나눌 수없는 chunkSize
등) 를 정상적으로 처리하려면 추가 코드가 필요할 수 있습니다 . 원래 질문은 이러한 경우에 대한 요구 사항을 지정하지 않으며 실제 상황에서는 요구 사항이 다를 수 있으므로이 답변의 범위를 벗어납니다.
답변
dove + Konstatin의 답변의 조합에서 …
static IEnumerable<string> WholeChunks(string str, int chunkSize) {
for (int i = 0; i < str.Length; i += chunkSize)
yield return str.Substring(i, chunkSize);
}
이것은 다수의 청크로 분할 될 수있는 모든 문자열에 대해 작동하며 그렇지 않으면 예외를 발생시킵니다.
임의의 길이의 문자열을 지원하려면 다음 코드를 사용할 수 있습니다.
static IEnumerable<string> ChunksUpto(string str, int maxChunkSize) {
for (int i = 0; i < str.Length; i += maxChunkSize)
yield return str.Substring(i, Math.Min(maxChunkSize, str.Length-i));
}
그러나 OP는 명시 적으로 이것을 필요로 하지 않는다고 명시했다 . 읽기가 다소 길고 어렵고 약간 느립니다. KISS와 YAGNI의 정신으로, 나는 첫 번째 옵션을 사용할 것입니다 : 아마도 가장 효율적인 구현 일 것입니다. 매우 짧고 읽기 쉽고 중요하지 않은 입력에 대한 예외가 발생합니다.
답변
왜 루프하지 않습니까? 여기에 아주 좋은 일이 있습니다.
string str = "111122223333444455";
int chunkSize = 4;
int stringLength = str.Length;
for (int i = 0; i < stringLength ; i += chunkSize)
{
if (i + chunkSize > stringLength) chunkSize = stringLength - i;
Console.WriteLine(str.Substring(i, chunkSize));
}
Console.ReadLine();
문자열이 4의 요소가 아닌 경우를 어떻게 처리 해야할지 모르겠지만 아이디어가 없다고 말하는 것은 불가능합니다. 단순한 for 루프가 잘 수행한다면 그 동기가 궁금하십니까? 분명히 위의 내용물을 청소하고 확장 방법으로 넣을 수도 있습니다.
또는 의견에서 언급했듯이 / 4임을 알고 있습니다.
str = "1111222233334444";
for (int i = 0; i < stringLength; i += chunkSize)
{Console.WriteLine(str.Substring(i, chunkSize));}
답변
사용 정규 표현식 과 Linq에를 :
List<string> groups = (from Match m in Regex.Matches(str, @"\d{4}")
select m.Value).ToList();
나는 이것이 더 읽기 쉽다는 것을 알지만, 그것은 개인적인 견해 일뿐입니다. 또한 하나의 라이너 일 수도 있습니다 :).
답변
이것은 @dove 솔루션을 기반으로 하지만 확장 방법으로 구현됩니다.
혜택:
- 확장 방법
- 코너 케이스 커버
- 문자열을 숫자, 문자, 기타 기호로 구분합니다.
암호
public static class EnumerableEx
{
public static IEnumerable<string> SplitBy(this string str, int chunkLength)
{
if (String.IsNullOrEmpty(str)) throw new ArgumentException();
if (chunkLength < 1) throw new ArgumentException();
for (int i = 0; i < str.Length; i += chunkLength)
{
if (chunkLength + i > str.Length)
chunkLength = str.Length - i;
yield return str.Substring(i, chunkLength);
}
}
}
용법
var result = "bobjoecat".SplitBy(3); // bob, joe, cat
간결성을 위해 단위 테스트가 제거되었습니다 ( 이전 개정 참조 ).
답변
원 라이너는 어때?
List<string> result = new List<string>(Regex.Split(target, @"(?<=\G.{4})", RegexOptions.Singleline));
이 정규 표현식을 사용하면 마지막 청크가 4 자 미만인지 여부는 중요하지 않습니다. 왜냐하면 그 뒤에 나오는 문자 만 볼 수 있기 때문입니다.
나는 이것이 가장 효율적인 해결책은 아니라고 확신하지만 거기에서 그것을 던져야했습니다.
답변
예쁘지 않고 빠르지는 않지만 작동하지만 하나의 라이너이며 LINQy입니다.
List<string> a = text.Select((c, i) => new { Char = c, Index = i }).GroupBy(o => o.Index / 4).Select(g => new String(g.Select(o => o.Char).ToArray())).ToList();
