Select 行来自基于 ID 列表的 CSV

Select rows from CSV based on a list of IDs

我的任务是从包含指定 ID 的 CSV 文件中提取几十万行。所以我有大约 300,000 个 ID 存储在一个字符串列表中,需要提取 CSV 中包含任何这些 ID 的任何行。 目前我正在使用 Linq 语句查看每一行是否包含列表中的任何 ID:

using (StreamReader sr = new StreamReader(csvFile))
{             
    string inLine = sr.ReadLine();
    if(searchStrings.Any(sr.ReadLine().Contains))
    {
         stremWriter.Write(inLine);
    }
}

这种方法可以,但速度很慢,因为 searchStrings 列表中有 300,000 个值,而我需要搜索的 CSV 文件中有几百万行。

有谁知道如何使此搜索更有效以加快速度? 或者提取所需行的替代方法?

谢谢

我以前遇到过类似的问题,我不得不遍历几十万行 .csv 并解析每一行。

我采用了一种线程化方法,尝试同时分批进行读取和解析。 这是大致我是如何做到的;

    using System.Collections.Concurrent; using System.Threading;
    private static ConcurrentBag<String> items = new ConcurrentBag<String>();
    private static List<String> searchStrings;
    static void Main(string[] args)
    {

        using (StreamReader sr = new StreamReader(csvFile))
        {
            const int buffer_size = 10000;
            string[] buffer = new string[buffer_size];

            int count = 0;
            String line = null;
            while ((line = sr.ReadLine()) != null)
            {
                buffer[count] = line;
                count++;
                if (count == buffer_size)
                {
                    new Thread(() =>
                        {
                            find(buffer);
                        }).Start();

                    buffer = new String[buffer_size];
                    count = 0;
                }
            }

            if (count > 0)
            {
                find(buffer);
            }

            //some kind of sync here, can be done with a bool - make sure all the threads have finished executing
            foreach (var str in searchStrings)
                streamWriter.write(str);
        }
    }

    private static void find(string[] buffer)
    {
        //do your search algorithm on the array of strings
       //add to the concurrentbag if they match
    }

我只是快速地将这段代码从我记得以前做过的事情中拼凑起来,所以它可能不完全正确。这样做肯定会加快速度(至少对于非常大的文件)。

想法是始终从硬盘读取,因为字符串解析可能非常昂贵,因此在多核上批处理工作可以显着加快速度。

有了这个,我能够解析(将每行分成大约 50 个项目并解析 key/value 对并从中构建内存中的对象 - 迄今为止最耗时的部分)大约 250k 行刚刚超过 7 秒。

只是把它扔在那里,它与您问题中的任何标签都没有特别相关,但 *nix "grep -f" 功能可以在这里使用。本质上,您将拥有一个包含要匹配的字符串列表的文件(例如,StringsToFind.txt),并且您将拥有您的 csv 输入文件(例如,input.csv),以下命令将输出output.csv

的匹配行

grep -f StringsToFind.txt input.csv > output.csv

有关详细信息,请参阅 grep man page