Giả sử tôi có một chuỗi:
string str = "1111222233334444";
Làm thế nào tôi có thể phá vỡ chuỗi này thành khối có kích thước?
ví dụ: phá vỡ điều này thành kích thước của 4 sẽ trả về chuỗi:
"1111"
"2222"
"3333"
"4444"
Giả sử tôi có một chuỗi:
string str = "1111222233334444";
Làm thế nào tôi có thể phá vỡ chuỗi này thành khối có kích thước?
ví dụ: phá vỡ điều này thành kích thước của 4 sẽ trả về chuỗi:
"1111"
"2222"
"3333"
"4444"
Câu trả lời:
static IEnumerable<string> Split(string str, int chunkSize)
{
return Enumerable.Range(0, str.Length / chunkSize)
.Select(i => str.Substring(i * chunkSize, chunkSize));
}
Xin lưu ý rằng mã bổ sung có thể được yêu cầu để xử lý một cách duyên dáng các trường hợp cạnh ( null
hoặc chuỗi đầu vào trống chunkSize == 0
, độ dài chuỗi đầu vào không chia hết cho chunkSize
, v.v.). Câu hỏi ban đầu không chỉ định bất kỳ yêu cầu nào cho các trường hợp cạnh này và trong thực tế, các yêu cầu có thể thay đổi để chúng nằm ngoài phạm vi của câu trả lời này.
(i * chunkSize + chunkSize <= str.Length) ? chunkSize : str.Length - i * chunkSize
. Một vấn đề khác là chức năng này không giải thích cho str là null. Điều này có thể được khắc phục bằng cách gói toàn bộ câu lệnh return trong một biểu thức ternary khác : (str != null) ? ... : Enumerable.Empty<String>();
.
str.Length / chunkSize
sangdouble length = str.Length; double size = chunkSize; int count = (int)Math.Ceiling(length/size); return Enumerable.Range(0, count)...
StringLength % 4 will always be 0
. Nếu Linq
không dễ hiểu thì có những câu trả lời khác sử dụng vòng lặp và sản lượng. Bất cứ ai cũng được tự do lựa chọn giải pháp cô ấy thích nhất. Bạn có thể đăng mã của mình dưới dạng câu trả lời và mọi người sẽ vui vẻ bỏ phiếu cho nó.
Trong sự kết hợp của câu trả lời của bồ câu + Konstatin ...
static IEnumerable<string> WholeChunks(string str, int chunkSize) {
for (int i = 0; i < str.Length; i += chunkSize)
yield return str.Substring(i, chunkSize);
}
Điều này sẽ làm việc cho tất cả các chuỗi có thể được chia thành một số lượng lớn và sẽ ném một ngoại lệ khác.
Nếu bạn muốn hỗ trợ các chuỗi có độ dài bất kỳ, bạn có thể sử dụng mã sau đây:
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));
}
Tuy nhiên, OP tuyên bố rõ ràng rằng anh ta không cần điều này; Nó hơi dài và khó đọc hơn, chậm hơn một chút. Theo tinh thần của KISS và YAGNI, tôi sẽ chọn tùy chọn đầu tiên: đó có thể là cách triển khai hiệu quả nhất có thể, và nó rất ngắn, dễ đọc và quan trọng là ném ra một ngoại lệ cho đầu vào không phù hợp.
Tại sao không phải là vòng lặp? Đây là một cái gì đó sẽ làm điều đó khá tốt:
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();
Tôi không biết làm thế nào bạn đối phó với trường hợp chuỗi không phải là yếu tố 4, nhưng không nói rằng ý tưởng của bạn là không thể, chỉ tự hỏi động lực cho nó nếu một vòng lặp đơn giản làm điều đó rất tốt? Rõ ràng những điều trên có thể được làm sạch và thậm chí đưa vào như một phương pháp mở rộng.
Hoặc như đã đề cập trong các bình luận, bạn biết đó là / 4 rồi
str = "1111222233334444";
for (int i = 0; i < stringLength; i += chunkSize)
{Console.WriteLine(str.Substring(i, chunkSize));}
int chunkSize = 4
ngoài vòng lặp. Nó sẽ chỉ được sửa đổi trên đường chuyền cuối cùng.
i += chunkSize
thay thế.
str.Length
ra khỏi vòng lặp và vào một biến cục bộ. Trình tối ưu hóa C # có thể có độ dài mảng nội tuyến, nhưng tôi nghĩ mã được viết sẽ thực hiện một cuộc gọi phương thức trên mỗi vòng lặp, không hiệu quả, vì kích thước str
không bao giờ thay đổi.
Sử dụng biểu thức chính quy và Linq :
List<string> groups = (from Match m in Regex.Matches(str, @"\d{4}")
select m.Value).ToList();
Tôi thấy điều này dễ đọc hơn, nhưng đó chỉ là ý kiến cá nhân. Nó cũng có thể là một lót :).
\d
lớp nhân vật bằng một .
và chỉ định RegexOptions.Singleline
.
Điều này dựa trên giải pháp @dove nhưng được triển khai như một phương thức mở rộng.
Những lợi ích:
Mã
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);
}
}
}
Sử dụng
var result = "bobjoecat".SplitBy(3); // bob, joe, cat
Các bài kiểm tra đơn vị được gỡ bỏ cho ngắn gọn (xem bản sửa đổi trước đó )
if (str.Length == 0) yield return String.Empty; else { for... }
IEnumerable
chuyển sang mảng, đặc biệt là không ngầm.
Chunkify
.. Nó không phải của tôi, tôi không nhớ tôi đã thấy cái tên đó ở đâu, nhưng tôi cảm thấy rất tuyệt
Làm thế nào điều này cho một lót?
List<string> result = new List<string>(Regex.Split(target, @"(?<=\G.{4})", RegexOptions.Singleline));
Với regex này, không có vấn đề gì nếu đoạn cuối cùng có ít hơn bốn ký tự, bởi vì nó chỉ nhìn vào các ký tự đằng sau nó.
Tôi chắc chắn đây không phải là giải pháp hiệu quả nhất, nhưng tôi phải ném nó ra khỏi đó.
target.Lenght % ChunckSize == 0
lợi nhuận mà một thêm trống hàng ví dụList<string> result = new List<string>(Regex.Split("fooo", @"(?<=\G.{4})", RegexOptions.Singleline));
Nó không đẹp và không nhanh, nhưng nó hoạt động, nó là một lớp lót và đó là 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();
ToCharArray
là không cần thiết vì string
là IEnumerable<char>
.
Gần đây tôi đã phải viết một cái gì đó thực hiện điều này trong công việc, vì vậy tôi nghĩ rằng tôi sẽ đăng giải pháp của mình cho vấn đề này. Là một phần thưởng bổ sung, chức năng của giải pháp này cung cấp một cách để phân tách chuỗi theo hướng ngược lại và nó xử lý chính xác các ký tự unicode như Marvin Pinto đã đề cập ở trên. Vì vậy, đây là:
using System;
using Extensions;
namespace TestCSharp
{
class Program
{
static void Main(string[] args)
{
string asciiStr = "This is a string.";
string unicodeStr = "これは文字列です。";
string[] array1 = asciiStr.Split(4);
string[] array2 = asciiStr.Split(-4);
string[] array3 = asciiStr.Split(7);
string[] array4 = asciiStr.Split(-7);
string[] array5 = unicodeStr.Split(5);
string[] array6 = unicodeStr.Split(-5);
}
}
}
namespace Extensions
{
public static class StringExtensions
{
/// <summary>Returns a string array that contains the substrings in this string that are seperated a given fixed length.</summary>
/// <param name="s">This string object.</param>
/// <param name="length">Size of each substring.
/// <para>CASE: length > 0 , RESULT: String is split from left to right.</para>
/// <para>CASE: length == 0 , RESULT: String is returned as the only entry in the array.</para>
/// <para>CASE: length < 0 , RESULT: String is split from right to left.</para>
/// </param>
/// <returns>String array that has been split into substrings of equal length.</returns>
/// <example>
/// <code>
/// string s = "1234567890";
/// string[] a = s.Split(4); // a == { "1234", "5678", "90" }
/// </code>
/// </example>
public static string[] Split(this string s, int length)
{
System.Globalization.StringInfo str = new System.Globalization.StringInfo(s);
int lengthAbs = Math.Abs(length);
if (str == null || str.LengthInTextElements == 0 || lengthAbs == 0 || str.LengthInTextElements <= lengthAbs)
return new string[] { str.ToString() };
string[] array = new string[(str.LengthInTextElements % lengthAbs == 0 ? str.LengthInTextElements / lengthAbs: (str.LengthInTextElements / lengthAbs) + 1)];
if (length > 0)
for (int iStr = 0, iArray = 0; iStr < str.LengthInTextElements && iArray < array.Length; iStr += lengthAbs, iArray++)
array[iArray] = str.SubstringByTextElements(iStr, (str.LengthInTextElements - iStr < lengthAbs ? str.LengthInTextElements - iStr : lengthAbs));
else // if (length < 0)
for (int iStr = str.LengthInTextElements - 1, iArray = array.Length - 1; iStr >= 0 && iArray >= 0; iStr -= lengthAbs, iArray--)
array[iArray] = str.SubstringByTextElements((iStr - lengthAbs < 0 ? 0 : iStr - lengthAbs + 1), (iStr - lengthAbs < 0 ? iStr + 1 : lengthAbs));
return array;
}
}
}
Ngoài ra, đây là một liên kết hình ảnh đến kết quả của việc chạy mã này: http://i.imgur.com/16Iih.png
{str.ToString()}
ở cuối câu lệnh IF đầu tiên. Bạn có chắc là bạn không cố ý str.String
? Tôi đã có một vấn đề với mã ở trên, thực hiện thay đổi đó và mọi thứ đều hoạt động.
Điều này sẽ nhanh hơn và hiệu quả hơn nhiều so với sử dụng LINQ hoặc các phương pháp khác được sử dụng ở đây.
public static IEnumerable<string> Splice(this string s, int spliceLength)
{
if (s == null)
throw new ArgumentNullException("s");
if (spliceLength < 1)
throw new ArgumentOutOfRangeException("spliceLength");
if (s.Length == 0)
yield break;
var start = 0;
for (var end = spliceLength; end < s.Length; end += spliceLength)
{
yield return s.Substring(start, spliceLength);
start = end;
}
yield return s.Substring(start);
}
public static IEnumerable<IEnumerable<T>> SplitEvery<T>(this IEnumerable<T> values, int n)
{
var ls = values.Take(n);
var rs = values.Skip(n);
return ls.Any() ?
Cons(ls, SplitEvery(rs, n)) :
Enumerable.Empty<IEnumerable<T>>();
}
public static IEnumerable<T> Cons<T>(T x, IEnumerable<T> xs)
{
yield return x;
foreach (var xi in xs)
yield return xi;
}
Bạn có thể sử dụng morelinq của Jon Skeet. Sử dụng hàng loạt như:
string str = "1111222233334444";
int chunkSize = 4;
var chunks = str.Batch(chunkSize).Select(r => new String(r.ToArray()));
Điều này sẽ trả về 4 khối cho chuỗi "1111222233334444"
. Nếu độ dài chuỗi nhỏ hơn hoặc bằng kích thước khối Batch
sẽ trả về chuỗi là phần tử duy nhất củaIEnumerable<string>
Đối với đầu ra:
foreach (var chunk in chunks)
{
Console.WriteLine(chunk);
}
và nó sẽ cho:
1111
2222
3333
4444
static IEnumerable<string> Split(string str, double chunkSize)
{
return Enumerable.Range(0, (int) Math.Ceiling(str.Length/chunkSize))
.Select(i => new string(str
.Skip(i * (int)chunkSize)
.Take((int)chunkSize)
.ToArray()));
}
và một cách tiếp cận khác:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var x = "Hello World";
foreach(var i in x.ChunkString(2)) Console.WriteLine(i);
}
}
public static class Ext{
public static IEnumerable<string> ChunkString(this string val, int chunkSize){
return val.Select((x,i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/chunkSize, x => x.Value)
.Select(x => string.Join("",x));
}
}
Sáu năm sau o_O
Chỉ vì
public static IEnumerable<string> Split(this string str, int chunkSize, bool remainingInFront)
{
var count = (int) Math.Ceiling(str.Length/(double) chunkSize);
Func<int, int> start = index => remainingInFront ? str.Length - (count - index)*chunkSize : index*chunkSize;
Func<int, int> end = index => Math.Min(str.Length - Math.Max(start(index), 0), Math.Min(start(index) + chunkSize - Math.Max(start(index), 0), chunkSize));
return Enumerable.Range(0, count).Select(i => str.Substring(Math.Max(start(i), 0),end(i)));
}
hoặc là
private static Func<bool, int, int, int, int, int> start = (remainingInFront, length, count, index, size) =>
remainingInFront ? length - (count - index) * size : index * size;
private static Func<bool, int, int, int, int, int, int> end = (remainingInFront, length, count, index, size, start) =>
Math.Min(length - Math.Max(start, 0), Math.Min(start + size - Math.Max(start, 0), size));
public static IEnumerable<string> Split(this string str, int chunkSize, bool remainingInFront)
{
var count = (int)Math.Ceiling(str.Length / (double)chunkSize);
return Enumerable.Range(0, count).Select(i => str.Substring(
Math.Max(start(remainingInFront, str.Length, count, i, chunkSize), 0),
end(remainingInFront, str.Length, count, i, chunkSize, start(remainingInFront, str.Length, count, i, chunkSize))
));
}
AFAIK tất cả các trường hợp cạnh được xử lý.
Console.WriteLine(string.Join(" ", "abc".Split(2, false))); // ab c
Console.WriteLine(string.Join(" ", "abc".Split(2, true))); // a bc
Console.WriteLine(string.Join(" ", "a".Split(2, true))); // a
Console.WriteLine(string.Join(" ", "a".Split(2, false))); // a
static IEnumerable<string> Split(string str, int chunkSize)
{
IEnumerable<string> retVal = Enumerable.Range(0, str.Length / chunkSize)
.Select(i => str.Substring(i * chunkSize, chunkSize))
if (str.Length % chunkSize > 0)
retVal = retVal.Append(str.Substring(str.Length / chunkSize * chunkSize, str.Length % chunkSize));
return retVal;
}
Nó xử lý chính xác độ dài chuỗi đầu vào không chia hết cho chunkSize.
Xin lưu ý rằng mã bổ sung có thể được yêu cầu để xử lý một cách duyên dáng các trường hợp cạnh (chuỗi đầu vào rỗng hoặc rỗng, chunkSize == 0).
Một mẹo quan trọng nếu chuỗi đang được phân đoạn cần hỗ trợ tất cả các ký tự Unicode.
Nếu chuỗi là để hỗ trợ các ký tự quốc tế như thế 𠀋
, thì hãy tách chuỗi bằng cách sử dụng lớp System.Globalization.StringInfo. Sử dụng StringInfo, bạn có thể tách chuỗi dựa trên số phần tử văn bản.
string internationalString = '𠀋';
Chuỗi trên có Độ dài là 2, vì thuộc String.Length
tính trả về số lượng đối tượng Char trong trường hợp này, chứ không phải số lượng ký tự Unicode.
Câu trả lời hay nhất, dễ nhất và chung chung :).
string originalString = "1111222233334444";
List<string> test = new List<string>();
int chunkSize = 4; // change 4 with the size of strings you want.
for (int i = 0; i < originalString.Length; i = i + chunkSize)
{
if (originalString.Length - i >= chunkSize)
test.Add(originalString.Substring(i, chunkSize));
else
test.Add(originalString.Substring(i,((originalString.Length - i))));
}
Substring
quá tải không yêu cầu tham số độ dài originalString.Substring(i)
. Ngoài ra, bạn có thể sử dụng >
thay vì >=
trong kiểm tra của bạn.
Cá nhân tôi thích giải pháp của mình :-)
Nó xử lý:
Nó được thực hiện như một phương thức mở rộng và nó tính toán số lượng khối sẽ tạo ra trước đó. Nó kiểm tra đoạn cuối bởi vì trong trường hợp độ dài văn bản không phải là bội số thì nó cần phải ngắn hơn. Sạch sẽ, ngắn gọn, dễ hiểu ... và hoạt động!
public static string[] Split(this string value, int chunkSize)
{
if (string.IsNullOrEmpty(value)) throw new ArgumentException("The string cannot be null.");
if (chunkSize < 1) throw new ArgumentException("The chunk size should be equal or greater than one.");
int remainder;
int divResult = Math.DivRem(value.Length, chunkSize, out remainder);
int numberOfChunks = remainder > 0 ? divResult + 1 : divResult;
var result = new string[numberOfChunks];
int i = 0;
while (i < numberOfChunks - 1)
{
result[i] = value.Substring(i * chunkSize, chunkSize);
i++;
}
int lastChunkSize = remainder > 0 ? remainder : chunkSize;
result[i] = value.Substring(i * chunkSize, lastChunkSize);
return result;
}
List<string> SplitString(int chunk, string input)
{
List<string> list = new List<string>();
int cycles = input.Length / chunk;
if (input.Length % chunk != 0)
cycles++;
for (int i = 0; i < cycles; i++)
{
try
{
list.Add(input.Substring(i * chunk, chunk));
}
catch
{
list.Add(input.Substring(i * chunk));
}
}
return list;
}
Tôi nghĩ rằng đây là một câu trả lời thẳng về phía trước:
public static IEnumerable<string> Split(this string str, int chunkSize)
{
if(string.IsNullOrEmpty(str) || chunkSize<1)
throw new ArgumentException("String can not be null or empty and chunk size should be greater than zero.");
var chunkCount = str.Length / chunkSize + (str.Length % chunkSize != 0 ? 1 : 0);
for (var i = 0; i < chunkCount; i++)
{
var startIndex = i * chunkSize;
if (startIndex + chunkSize >= str.Length)
yield return str.Substring(startIndex);
else
yield return str.Substring(startIndex, chunkSize);
}
}
Và nó bao gồm các trường hợp cạnh.
Tôi biết câu hỏi đã có tuổi, nhưng đây là một triển khai Rx. Nó xử lý length % chunkSize != 0
vấn đề ra khỏi hộp:
public static IEnumerable<string> Chunkify(this string input, int size)
{
if(size < 1)
throw new ArgumentException("size must be greater than 0");
return input.ToCharArray()
.ToObservable()
.Buffer(size)
.Select(x => new string(x.ToArray()))
.ToEnumerable();
}
Tôi đã xây dựng một chút về giải pháp của João. Những gì tôi đã làm khác nhau là trong phương thức của tôi, bạn thực sự có thể chỉ định xem bạn muốn trả về mảng với các ký tự còn lại hay bạn muốn cắt bớt chúng nếu các ký tự kết thúc không khớp với độ dài đoạn yêu cầu của bạn, tôi nghĩ nó khá linh hoạt và mã khá đơn giản:
using System;
using System.Linq;
using System.Text.RegularExpressions;
namespace SplitFunction
{
class Program
{
static void Main(string[] args)
{
string text = "hello, how are you doing today?";
string[] chunks = SplitIntoChunks(text, 3,false);
if (chunks != null)
{
chunks.ToList().ForEach(e => Console.WriteLine(e));
}
Console.ReadKey();
}
private static string[] SplitIntoChunks(string text, int chunkSize, bool truncateRemaining)
{
string chunk = chunkSize.ToString();
string pattern = truncateRemaining ? ".{" + chunk + "}" : ".{1," + chunk + "}";
string[] chunks = null;
if (chunkSize > 0 && !String.IsNullOrEmpty(text))
chunks = (from Match m in Regex.Matches(text,pattern)select m.Value).ToArray();
return chunks;
}
}
}
public static List<string> SplitByMaxLength(this string str)
{
List<string> splitString = new List<string>();
for (int index = 0; index < str.Length; index += MaxLength)
{
splitString.Add(str.Substring(index, Math.Min(MaxLength, str.Length - index)));
}
return splitString;
}
Thay đổi một chút để trả về các phần có kích thước không bằng chunkSize
public static IEnumerable<string> Split(this string str, int chunkSize)
{
var splits = new List<string>();
if (str.Length < chunkSize) { chunkSize = str.Length; }
splits.AddRange(Enumerable.Range(0, str.Length / chunkSize).Select(i => str.Substring(i * chunkSize, chunkSize)));
splits.Add(str.Length % chunkSize > 0 ? str.Substring((str.Length / chunkSize) * chunkSize, str.Length - ((str.Length / chunkSize) * chunkSize)) : string.Empty);
return (IEnumerable<string>)splits;
}
List
đến IEnumerable
; tất cả những gì làm là ẩn các chức năng cụ thể của Danh sách mà bạn có thể muốn sử dụng. Không có bất kỳ nhược điểm nào khi chỉ trả lại List
.
Tôi không thể nhớ ai đã cho tôi cái này, nhưng nó hoạt động rất tốt. Tôi đã kiểm tra tốc độ một số cách để chia nhiều loại thành nhiều nhóm. Việc sử dụng sẽ như thế này ...
List<string> Divided = Source3.Chunk(24).Select(Piece => string.Concat<char>(Piece)).ToList();
Mã mở rộng sẽ trông như thế này ...
#region Chunk Logic
private class ChunkedEnumerable<T> : IEnumerable<T>
{
class ChildEnumerator : IEnumerator<T>
{
ChunkedEnumerable<T> parent;
int position;
bool done = false;
T current;
public ChildEnumerator(ChunkedEnumerable<T> parent)
{
this.parent = parent;
position = -1;
parent.wrapper.AddRef();
}
public T Current
{
get
{
if (position == -1 || done)
{
throw new InvalidOperationException();
}
return current;
}
}
public void Dispose()
{
if (!done)
{
done = true;
parent.wrapper.RemoveRef();
}
}
object System.Collections.IEnumerator.Current
{
get { return Current; }
}
public bool MoveNext()
{
position++;
if (position + 1 > parent.chunkSize)
{
done = true;
}
if (!done)
{
done = !parent.wrapper.Get(position + parent.start, out current);
}
return !done;
}
public void Reset()
{
// per http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.reset.aspx
throw new NotSupportedException();
}
}
EnumeratorWrapper<T> wrapper;
int chunkSize;
int start;
public ChunkedEnumerable(EnumeratorWrapper<T> wrapper, int chunkSize, int start)
{
this.wrapper = wrapper;
this.chunkSize = chunkSize;
this.start = start;
}
public IEnumerator<T> GetEnumerator()
{
return new ChildEnumerator(this);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
private class EnumeratorWrapper<T>
{
public EnumeratorWrapper(IEnumerable<T> source)
{
SourceEumerable = source;
}
IEnumerable<T> SourceEumerable { get; set; }
Enumeration currentEnumeration;
class Enumeration
{
public IEnumerator<T> Source { get; set; }
public int Position { get; set; }
public bool AtEnd { get; set; }
}
public bool Get(int pos, out T item)
{
if (currentEnumeration != null && currentEnumeration.Position > pos)
{
currentEnumeration.Source.Dispose();
currentEnumeration = null;
}
if (currentEnumeration == null)
{
currentEnumeration = new Enumeration { Position = -1, Source = SourceEumerable.GetEnumerator(), AtEnd = false };
}
item = default(T);
if (currentEnumeration.AtEnd)
{
return false;
}
while (currentEnumeration.Position < pos)
{
currentEnumeration.AtEnd = !currentEnumeration.Source.MoveNext();
currentEnumeration.Position++;
if (currentEnumeration.AtEnd)
{
return false;
}
}
item = currentEnumeration.Source.Current;
return true;
}
int refs = 0;
// needed for dispose semantics
public void AddRef()
{
refs++;
}
public void RemoveRef()
{
refs--;
if (refs == 0 && currentEnumeration != null)
{
var copy = currentEnumeration;
currentEnumeration = null;
copy.Source.Dispose();
}
}
}
/// <summary>Speed Checked. Works Great!</summary>
public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> source, int chunksize)
{
if (chunksize < 1) throw new InvalidOperationException();
var wrapper = new EnumeratorWrapper<T>(source);
int currentPos = 0;
T ignore;
try
{
wrapper.AddRef();
while (wrapper.Get(currentPos, out ignore))
{
yield return new ChunkedEnumerable<T>(wrapper, chunksize, currentPos);
currentPos += chunksize;
}
}
finally
{
wrapper.RemoveRef();
}
}
#endregion
class StringHelper
{
static void Main(string[] args)
{
string str = "Hi my name is vikas bansal and my email id is bansal.vks@gmail.com";
int offSet = 10;
List<string> chunks = chunkMyStr(str, offSet);
Console.Read();
}
static List<string> chunkMyStr(string str, int offSet)
{
List<string> resultChunks = new List<string>();
for (int i = 0; i < str.Length; i += offSet)
{
string temp = str.Substring(i, (str.Length - i) > offSet ? offSet : (str.Length - i));
Console.WriteLine(temp);
resultChunks.Add(temp);
}
return resultChunks;
}
}
i += offSet
thành for
biểu thức của bạn .
Sửa đổi (bây giờ nó chấp nhận bất cứ rỗng không string
và bất kỳ dương chunkSize
) Konstantin Spirin 's giải pháp:
public static IEnumerable<String> Split(String value, int chunkSize) {
if (null == value)
throw new ArgumentNullException("value");
else if (chunkSize <= 0)
throw new ArgumentOutOfRangeException("chunkSize", "Chunk size should be positive");
return Enumerable
.Range(0, value.Length / chunkSize + ((value.Length % chunkSize) == 0 ? 0 : 1))
.Select(index => (index + 1) * chunkSize < value.Length
? value.Substring(index * chunkSize, chunkSize)
: value.Substring(index * chunkSize));
}
Các xét nghiệm:
String source = @"ABCDEF";
// "ABCD,EF"
String test1 = String.Join(",", Split(source, 4));
// "AB,CD,EF"
String test2 = String.Join(",", Split(source, 2));
// "ABCDEF"
String test3 = String.Join(",", Split(source, 123));
static List<string> GetChunks(string value, int chunkLength)
{
var res = new List<string>();
int count = (value.Length / chunkLength) + (value.Length % chunkLength > 0 ? 1 : 0);
Enumerable.Range(0, count).ToList().ForEach(f => res.Add(value.Skip(f * chunkLength).Take(chunkLength).Select(z => z.ToString()).Aggregate((a,b) => a+b)));
return res;
}
Dựa trên các câu trả lời của người đăng khác, cùng với một số mẫu sử dụng:
public static string FormatSortCode(string sortCode)
{
return ChunkString(sortCode, 2, "-");
}
public static string FormatIBAN(string iban)
{
return ChunkString(iban, 4, " ");
}
private static string ChunkString(string str, int chunkSize, string separator)
{
var b = new StringBuilder();
var stringLength = str.Length;
for (var i = 0; i < stringLength; i += chunkSize)
{
if (i + chunkSize > stringLength) chunkSize = stringLength - i;
b.Append(str.Substring(i, chunkSize));
if (i+chunkSize != stringLength)
b.Append(separator);
}
return b.ToString();
}
Sử dụng các phần mở rộng Bộ đệm từ thư viện IX
static IEnumerable<string> Split( this string str, int chunkSize )
{
return str.Buffer(chunkSize).Select(l => String.Concat(l));
}