将一大组数据与另一组数据进行比较的绝对最快的方法是什么?

What is the absolute fastest way to compare one large set of data to another?

您有一个很大的独特项目列表(数十万行)。您想要查看这些项目是否存在于另一组数据中。另一组数据只是一个逐行排列的文件,也是一组唯一的数据。您可以将任何数据放入数据库,使用任何编程语言等。

你怎么比较这些最快?唯一的限制是硬件是普通服务器,而不是数据库服务器。最多一锭

摄氏?实现排序算法?用于索引等的数据库?

管理员取出了我用 "because the question is too broad" 给出的答案:python 中的布隆过滤器。使用 python 的布隆过滤器库非常容易实现。

您可以使用一个简单的 bash 脚本:

首先对列表进行排序

$ sort list1.txt > list1.sorted.txt
$ sort list2.txt > list2.sorted.txt

然后进行连接以查找两个列表的共同元素:

$ join -1 1 -2 1 list1.sorted.txt list2.sorted.txt

这应该比较快并且内存消耗低。

如果您的 "test" 文件大小合理,一个快速的解决方案是为该文件中的每个条目构建一个哈希映射。 C# 解决方案(在 Big O ( N ) 中运行)是这样的:

public static bool SetIsPresentIn(string firstFileLocation, string secondFileLocation)
        {
            HashSet<string> set = new HashSet<string> ();

            using (var sr = new FileStream(firstFileLocation, FileMode.Open, FileAccess.Read))
            {
                using (var reader = new StreamReader(sr))
                {
                    while (reader.EndOfStream == false )
                    {
                        var text = reader.ReadLine();
                        set.Add(text);
                    }
                }
            }

            // iterating through the first one!

            using (var secondFile = new FileStream(secondFileLocation, FileMode.Open, FileAccess.Read))
            {
                using (var reader = new StreamReader(secondFile))
                {
                    while (reader.EndOfStream == false)
                    {
                        var line = reader.ReadLine();
                        // perform a lookup!

                        if (set.Remove(line) && set.Count == 0)
                            return true;

                    }
                }
            }

            return set.Count == 0;
        }

否则我会做一件聪明的事情:将您的 "test" 文件拆分为文件分区:每个分区名称与每一行的哈希码相匹配。当迭代第二个文件时,只需创建一个哈希码并在从第一个文件构建的对应分区内搜索!

示例:

public static bool SetIsPresentInUsingFilePartitions(string firstFileLocation, string secondFileLocation, string partitionsRootLocation)
        {
            Dictionary<int, StreamWriter> partitionWriters = new Dictionary<int, StreamWriter>();

            Dictionary<int, string> locations = new Dictionary<int, string>();
            using (var sr = new FileStream(secondFileLocation, FileMode.Open, FileAccess.Read))
            {
                using (var reader = new StreamReader(sr))
                {
                    while (reader.EndOfStream == false)
                    {
                        var text = reader.ReadLine();
                        var hCode = text.GetHashCode();


                        var fileName = Path.Combine(partitionsRootLocation, hCode.ToString ());

                        if (false == partitionWriters.ContainsKey(hCode))
                        {
                            var fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);
                            partitionWriters[hCode] = new StreamWriter(fs);
                            locations[hCode] = fileName;
                        }

                        partitionWriters[hCode].WriteLine(text);
                    }
                }
            }

            // close writers 
            foreach (var item in partitionWriters)
                item.Value.Dispose();


            using (var sr = new FileStream(firstFileLocation, FileMode.Open, FileAccess.Read))
            {
                using (var reader = new StreamReader(sr))
                {
                    while (reader.EndOfStream == false)
                    {
                        var line = reader.ReadLine();
                        var hCode = line.GetHashCode();

                        string location;
                        if (false == locations.TryGetValue(hCode, out location))
                        {
                            return false; // tere's a line that is not found in the second file!

                        }

                        var found = false;
                        using (var file = new FileStream(location, FileMode.Open, FileAccess.Read))
                        {
                            using (var fs = new StreamReader(file))
                            {
                                while (fs.EndOfStream == false)
                                {
                                    var firstFileLine = fs.ReadLine();
                                    if (line == firstFileLine)
                                    {
                                        found = true;
                                        break;
                                    }

                                }
                            }


                        }

                        if (!found)
                            return false;
                    }
                }

            }

            return true;

        }