根据块大小(行数)将 List<string> 拆分为不同的 List

Split a List<string> into different Lists based on chunk size (Number of lines)

假设我有一个名为 "lines" 的大字符串列表,它包含文本文件中的所有行(通常是大约 100k - 100 万行的大数字)

List<string> lines = File.ReadAllLines("Lines.txt");

我的问题是我需要根据用户输入的块大小拆分文件(或列表)。所以假设我们有 10k 行 Lines.txt 并且用户输入了 4400 行的块

File1 = 4400 Lines 
File2 = 4400 Lines
File3 = 1200 Lines

我尝试使用我的同事推荐的类似的东西,但我不明白它并且它不起作用。

public static class ListExtensions
{
    public static List<List<T>> ChunkBy<T>(this List<T> source, int chunkSize) 
    {
        return source
            .Select((x, i) => new { Index = i, Value = x })
            .GroupBy(x => x.Index / chunkSize)
            .Select(x => x.Select(v => v.Value).ToList())
            .ToList();
    }
}

如有任何建议或帮助我解决此问题,我将不胜感激。

Linq 的 TakeSkip 在这里可能有所帮助。

public static List<List<T>> ChunkBy<T>(this List<T> source, int chunkSize) 
{
    var pages = new List<List<T>>();
    var page = 0;
    while(source.Any()) {
        var l = source.Skip(page++*chunkSize).Take(chunkSize).ToList();
        if(!l.Any()) break;
        pages.Add(l);
    }
    return pages;
}

这个怎么样 -

var numOfChunks = lines.Count / chunkSize; // initial number of chunks
if(lines.Count % chunkSize > 0) { numOfChunks++; } // add one chunk for remainder if there is a remainder
for (var i = 0; i <= numOfChunks; i++)
{
     var chunk = lines.Skip(i * chunkSize).Take(chunkSize);
    // Do something with chunk, like writing to file
}

这是一个没有 Linq 的版本。

public static List<List<T>> ChunkBy<T>(List<T> source, int chunkSize) 
{
    var pages = new List<List<T>>();
    var page = new List<T>();
    var i = 0;
    foreach( var s in source ) {
        if((i++ % chunkSize) == 0 ) { page = new List<T>(); pages.Add(page);}
        page.Add(s);
    }

    return pages;
}

这是您可以用于此任务的一种方法。您需要确保传递要分块的 sourceFile 文件、要写入文件的 destDirectory 以及分块大小。

private static void ChunkFile(string sourceFile, string destDirectory, int chunkSize)
{
    // Read all lines
    var lines = File.ReadLines(sourceFile)

    // Calculate number of chunks needed
    // Round up to get correct chunks
    var numberOfChunks = (int)Math.Ceiling((double)lines.Count() / chunkSize);

    // Go through each chunk and write to file
    for (var i = 0; i < numberOfChunks; i++)
    {
        // Skip lines chunks we've already seen, and take the next chunk
        var chunk = lines.Skip(i * chunkSize).Take(chunkSize);

        // Write chunk to destination path
        File.WriteAllLines(Path.Combine(destDirectory, $"File{i + 1}.txt"), chunk);
    }
}

它应该以 File1.txt、File2.txt、File3.txt.. 等格式生成分块文件

您还需要实施错误处理,例如检查 sourceFile 是否存在等。

另外,我建议看看 System.Linq 中的这两个 LINQ 方法:

查看 System.IO 到 read/write 文件中的这些 IO 方法可能也会有所帮助:

注意:我们使用File.ReadLines代替File.ReadAllLines to avoid reading the whole file into memory. This is needed when reading large files and decreasing performance. You can read more about this at What is the difference between File.ReadLines() and File.ReadAllLines()?