你有一个很大的独特项目列表(数十万行)。您想要查看这些项目是否存在于另一组数据中。另一组数据只是一个包含逐行项目的文件,也是一组唯一的数据。您可以将任何数据放入数据库,使用任何编程语言等。
你怎么做才能比较这些最快?唯一的限制是硬件是普通服务器,而不是数据库服务器。最多一个主轴
C 2实现排序算法? DB用于索引等?
管理员拿出了我的回答“因为问题太广泛了”:Bloom过滤器在python中。使用python的bloom过滤器库实现起来非常简单。
答案 0 :(得分:1)
您可以使用简单的bash脚本:
首先对列表进行排序
$ sort list1.txt > list1.sorted.txt
$ sort list2.txt > list2.sorted.txt
然后进行连接以找到两个列表的公共元素:
$ join -1 1 -2 1 list1.sorted.txt list2.sorted.txt
这应该相对较快并且内存消耗较低。
答案 1 :(得分:1)
如果你的"测试" file有一个合理的大小,一个快速的解决方案是为该文件中的每个条目构建一个哈希映射。 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;
}
否则我会做一个聪明的事情:分开你的&#34;测试&#34;文件分区中的文件:每个分区名称与每行的哈希码匹配。迭代第二个文件时,只需创建一个哈希码并在第一个文件构建的相应分区内搜索!
示例:
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;
}