سؤال

ربما سؤال أساسي ولكن لنفترض أن لدي سلسلة يبلغ طولها 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;
    }
}

لاحظ أن هذا يقسم إلى أجزاء من 16 UTF حدات التعليمات البرمجية، التي ليست هي نفسها تماما كما تنقسم الى قطع من نقطة رمز Unicode، والتي بدورها قد لا يكون هو نفسه تقسيم إلى قطع رموزا.

نصائح أخرى

وعلى الرغم من هذا السؤال له إجابة في الوقت نفسه مقبولة، وهنا مقطعة مع مساعدة من التعابير العادية. الأصوليون قد لا ترغب في ذلك (المفهوم) ولكن عندما كنت في حاجة الى حل سريع وكنت يدوية مع regexes، وهذا يمكن أن يكون عليه. أداء جيد إلى حد ما، من المستغرب:

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

وماذا يفعل؟ نظرة إلى الوراء سلبي وتذكر الموقف الاخير مع \G. وسوف قبض أيضا شيئا آخر، حتى لو كان لا يمكن تقسيمها 512.

باستخدام تنفيذ جون و أَثْمَر الكلمة الرئيسية.

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);
    }
}
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 من حل جون، واستنادا إلى حقيقة أن نوع 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) نتوقع على الأقل للعودة هذه السلسلة فارغة (نفس السلوك كما انقسام على شار ليس في السلسلة، والذي سوف يعيد عنصر واحد: أن سلسلة معينة)

وهكذا ينبغي لنا حلقة مرة واحدة على الأقل كل الأوقات (على أساس قانون جون في):

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

وأو باستخدام ل(على تعديل : في بعد اللعب أكثر من ذلك بقليل مع هذا، لقد وجدت طريقة أفضل للتعامل مع القضية <م> 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);
    }
}

ويمكن أيضا أن تستخدم هذا مع تأليف / في حين حلقة؛)

عام طريقة التمديد:

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);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top