我会给你三个选择(和奖金)。
第一个选项。使用使用迭代器块的自定义 Chunk(int) linq 运算符。诀窍是内部方法使用与外部相同的枚举器。看起来代码很多,但是一旦你有了Chunk() 方法,你就可以在任何地方使用它。另请注意,此选项甚至不需要List<string>。它适用于 any IEnumerable<string>,因为我们从不通过索引引用任何元素。
public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> values, int chunkSize)
{
var e = values.GetEnumerator();
while (e.MoveNext())
{
yield return innerChunk(e, chunkSize);
}
}
private static IEnumerable<T> innerChunk<T>(IEnumerator<T> e, int chunkSize)
{
//If we're here, MoveNext() was already called once to advance between batches
// Need to yield the value from that call.
yield return e.Current;
//start at 1, not 0, for the first yield above
int i = 1;
while(i++ < chunkSize && e.MoveNext()) //order of these conditions matters
{
yield return e.Current;
}
}
public static void WriteFormattedTextToNewFile(IEnumerable<string> groupedStrings)
{
string file = @"C:\Users\e011691\Desktop\New folder\formatted.txt";
using (var sw = new StreamWriter(file, true))
{
foreach(var strings in groupedStrings.Chunk(50))
{
sw.Write($"{DateTime.Now:yyyy MM dd hh:mm:ss}\t\t");
foreach(var item in strings)
{
sw.Write($"{item}\t");
}
sw.WriteLine();
}
}
}
这是一个基本的proof of concept Chunk() actually works。
作为奖励选项,这是使用第一个选项中的 Chunk() 方法的另一种方法。请注意实际方法变得多么小而直接,但是长整行字符串的构造可能会降低效率。
public static void WriteFormattedTextToNewFile(IEnumerable<string> groupedStrings)
{
string file = @"C:\Users\e011691\Desktop\New folder\formatted.txt";
using (var sw = new StreamWriter(file, true))
{
foreach(var strings in groupedStrings.Chunk(50))
{
sw.Write($"{DateTime.Now:yyyy MM dd hh:mm:ss}\t\t");
sw.WriteLine(string.Join("\t", strings));
}
}
}
第二个选项。使用单独的整数/循环跟踪。注意内部循环的额外条件,仍然使用i 值而不是j 来引用当前位置,并在内部循环中递增i。这称为控制/中断循环。请注意我们如何能够在每一行上写入结束行和初始日期值,以便它们在代码中也以正确的顺序出现:首先是页眉,然后是项目,然后是页脚,并且我们无需复杂的条件检查即可完成.
public static void WriteFormattedTextToNewFile(List<string> groupedStrings)
{
string file = @"C:\Users\e011691\Desktop\New folder\formatted.txt";
using (var sw = new StreamWriter(file, true))
{
int i = 0;
while(i < groupedStrings.Count)
{
sw.Write($"{DateTime.Now:yyyy MM dd hh:mm:ss}\t\t");
for(int j = 0; j < 50 && i < groupedStrings.Count; j++)
{
sw.Write($"{groupedStrings[i]}\t");
i++;
}
sw.WriteLine();
}
}
}
第三个选项。使用模数运算符 (%) 跟踪。此选项(或在同一循环中使用第二个 j 值的类似选项)是许多人首先转向的地方,但要小心;这个选项看起来很难正确,尤其是当问题变得更加复杂时。
public static void WriteFormattedTextToNewFile(List<string> groupedStrings)
{
string file = @"C:\Users\e011691\Desktop\New folder\formatted.txt";
using (var sw = new StreamWriter(file, true))
{
for(int i = 0; i < groupedStrings.Count;i++)
{
if (i % 50 == 0)
{
if (i > 0) sw.WriteLine();
sw.Write($"{DateTime.Now:yyyy MM dd hh:mm:ss}\t\t");
}
sw.Write($"{groupedStrings[i]}\t");
}
sw.WriteLine();
}
}
更新:
Chunk() 的变体现在包含在 .Net 6 的开箱即用中。