【问题标题】:Split large string into smaller chunks in c#在c#中将大字符串拆分成更小的块
【发布时间】:2012-04-27 11:41:45
【问题描述】:

我有一个由换行符分隔的大字符串。该字符串包含 100 行。我想将这些行分成小块,比如 20 块也基于换行符。

假设字符串变量是这样的,

Line1
这是line2
Line3在这里
我是Line4

现在我想把这个大字符串变量分成 2 个的小块。结果应该是 2 个字符串,

第1行
这是第2行


Line3来了
我是Line4

使用拆分功能,我没有得到预期的结果。请帮助我实现这一目标。

提前致谢,
维杰

【问题讨论】:

  • 在换行符上拆分会给你 4 个字符串,而不是两个......为什么你会期望有什么不同?
  • split 会给你 4 行。 y 不要合并这两个字符串 n 将它放在一个新数组中。
  • 使用 Split 和 String bulider 类。想想这对你有帮助

标签: c# .net


【解决方案1】:

简单的方法(在 Environment.NewLine 上拆分,然后循环和追加):

public static List<string> GetStringSegments(string originalString, int linesPerSegment)
{

    List<string> segments = new List<string>();
    string[] allLines = originalString.Split(new string[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries); 
    StringBuilder sb = new StringBuilder();

    int linesProcessed = 0;
    for (int i = 0; i < allLines.Length; i++)
    {
        sb.AppendLine(allLines[i]);
        linesProcessed++;

        if (linesProcessed == linesPerSegment
            || i == allLines.Length-1)
        {
            segments.Add(sb.ToString());
            sb.Clear();
            inesProcessed = 0;
        }
    }

    return segments;
}

上述方法效率稍低,因为它需要先将字符串拆分为单独的行,这会创建不必要的字符串。一个 1000 行的字符串将创建一个包含 1000 个字符串的数组。如果我们只扫描字符串并搜索\n,我们可以改进这一点:

public static List<string> GetStringSegments(string original, int linesPerSegment)
{
    List<string> segments = new List<string>();

    int startIndex = 0;
    int newLinesEncountered = 0;

    for (int i = 0; i < original.Length; i++)
    {
        if (original[i] == '\n')
        {
            newLinesEncountered++;
        }

        if (newLinesEncountered == linesPerSegment
            || i == original.Length - 1)
        {
            segments.Add(original.Substring(startIndex, (i - startIndex + 1)));
            startIndex = i + 1;
            newLinesEncountered = 0;
        }
    }

    return segments;
}

【讨论】:

    【解决方案2】:

    你可以使用类似http://www.make-awesome.com/2010/08/batch-or-partition-a-collection-with-linq的批处理操作符

    string s = "[YOUR DATA]";
    var lines = s.Split(new[]{Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
    foreach(var batch in lines.Batch(20))
    {
      foreach(batchLine in batch)
      {
        Console.Writeline(batchLine);
      }
    }
    
    static class LinqEx
    {
      // from http://www.make-awesome.com/2010/08/batch-or-partition-a-collection-with-linq
      public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> collection,
                    int batchSize)
      {
        List<T> nextbatch = new List<T>(batchSize);
        foreach (T item in collection)
        {
          nextbatch.Add(item);
          if (nextbatch.Count == batchSize)
          {
            yield return nextbatch;
            nextbatch = new List<T>(batchSize);
          }
        }
        if (nextbatch.Count > 0)
          yield return nextbatch;
      }
    }
    

    【讨论】:

      【解决方案3】:

      正如一些人提到的,使用string.Split 会将整个字符串拆分到内存中,这可能是一个分配繁重的操作。这就是为什么我们有 TextReader 类及其后代的原因,它们应该提供更好的内存性能,并且在逻辑上也可能更清晰:

      using (var reader = new StringReader(myString))
      {
          do
          {
              StringBuilder newString = null;
              StringWriter newStringWriter = null;
              if (lineCounter % 20 == 0)
              {
                   newString = new StringBuilder();
                   newStringWriter = new StringWriter(newString);
                   newStringCollection.Add(newString);
              } 
              string line = reader.ReadLine();
              if (!string.isNullOrEmpty(line))
              {
                   newStringWriter.WriteLine(line);
                   lineCounter++;
              }
          }
          while (line != null)
      }
      

      我们使用StringReader 读取我们的大字符串,一次一行。对应的StringWriter 将这些行写入新字符串,一次一行。每 20 行之后,我们启动一个新的 StringBuilder(以及相应的 StringWriter 包装器)。

      【讨论】:

        【解决方案4】:

        用换行符分割字符串。 然后在使用字符串时将字符串的数量合并/获取。

        【讨论】:

          【解决方案5】:
          string s = "Line1\nThis is line2 \nLine3 is here\nI am Line4";
          
          string [] str = s.split('\n');
          
          List<String> str1 = new List<String>();
          
          for(int i=0; i<str.Length; i+=2)
          {
              string ss = str[i];
          
              if(i+1 <str.Length)
                  ss += '\n' + str[i+1];
          
              str1.Add(ss);
          }
          
          str = str1.ToArray();
          

          如果条件已在循环内检查,因为 str 的长度可能是奇数

          【讨论】:

            【解决方案6】:
            var strAray = myLongString.Split('\n').ToList();
            var skip=0;
            var take=20;
            
            var chunk = strAray.Skip(skip).Take(take).ToList();
            
            While(chunk.Count >0)
            {
            foreach(var line in chunk)
            {
            // use line string
            }
            skip++;
            chunk = strAray.Skip(skip).Take(take).ToList()
            }
            

            【讨论】:

              猜你喜欢
              • 2021-06-24
              • 1970-01-01
              • 1970-01-01
              • 2011-10-25
              • 2014-02-16
              • 2022-12-05
              • 1970-01-01
              相关资源
              最近更新 更多