合并对象的有效方法
Efficient way to merge objects
我有一个比较大的"站点"列表,大约有350,000个。这些电台来自五个不同的来源,每个都有特定的信息片段。例如,它们都至少具有五种不同类型标识符中的一种。目标是合并相等的站点(如果站点有匹配的标识符,则站点是相等的)。
示例:如果站点a有identifierA: 01234、identifierB: NULL和identifierC: KAKW,站点b有identiferA: NULL、identifierB: USA00012和identifierC: KAKW,我想将它们合并在一起,作为一个具有identifierA: 01234、identifierB: USA00012和identifierC: KAKW的新站点。
现在我把所有的站都放在一个大向量上。我每次移动一个站点到一个新的向量中:1)如果它与向量中已有的任何站点不匹配,则将其推回去,或者2)如果有匹配,则将其合并。
这太花时间了。从理论上讲,是否有一个有效的算法或概念,我可以用来加速这个过程?上一次我花了将近3天的时间。
创建3个数据副本,每个副本用不同的标识符排序。
然后选择一个,迭代,并在已排序的容器中查找匹配。构建组合对象并将其保存到"processed"向量中。
看起来应该是一个哈希表类型的问题,但也许不是,因为有不止一种方法可以使两个站点相等。
我建议类似阿米特的答案,如果你可以节省内存。只是有5个std::map
容器的标识符作为索引进入主容器(如数据库),并做你的搜索方式。将标识符放入已排序的容器中需要做一些前期工作,但最终可能会更快。
如果你不关心哪个标识符匹配哪个,或者如果你的标识符数据集不相交,你可以只使用一个容器,将所有五个标识符组合在一起(可能是散列的,但可能不包括null),并在上面搜索。
下面的代码对站点进行传递,有效地生成该站点具有的标识符的位掩码。它翻转这些位以创建一个位掩码,这个位掩码是另一个只有缺失标识符的站点所具有的,如果这样的站点已经已知,则与它合并,将合并的站点添加到稍后将被擦除的列表中。否则,它将不匹配的站点添加到具有其特定位掩码的站点列表中,以便稍后可以快速找到它。(只做了很少的测试)
#include <iostream>
#include <string>
#include <vector>
struct Station
{
int idn_map() const { return 16 * bool(ia_[0]) +
8 * bool(ib_[0]) +
4 * bool(ic_[0]) +
2 * bool(id_[0]) +
bool(ie_[0]); }
void merge(const Station& rhs)
{
if (ia_.empty()) ia_ = rhs.ia_;
if (ib_.empty()) ib_ = rhs.ib_;
if (ic_.empty()) ic_ = rhs.ic_;
if (id_.empty()) id_ = rhs.id_;
if (ie_.empty()) ie_ = rhs.ie_;
}
std::string ia_, ib_, ic_, id_, ie_;
};
std::ostream& operator<<(std::ostream& os, const Station& s)
{
return os << s.ia_ << ':' << s.ib_ << ':' << s.ic_ << ':' << s.id_ << ':' << s.ie_;
}
int main()
{
std::vector<Station> stations = {
{ "s0a", "", "s0c", "", "s0e" },
{ "", "", "s1c", "s1d", "s1e" },
{ "", "s2b", "", "s2d", "" },
{ "s3a", "s3b", "s3c", "s3d", "" },
{ "s4a", "s4b", "", "", "" }
};
std::vector<Station*> unmatched[32];
std::vector<Station*> to_erase;
for (Station& s : stations)
{
int idn_map = s.idn_map();
if (unmatched[idn_map ^ 31].empty())
unmatched[idn_map].push_back(&s);
else
{
// merge from current element so to_erase kept sorted
// for fast compact/erase later...
Station* p_merge_to = unmatched[idn_map ^ 31].back();
p_merge_to->merge(s);
to_erase.push_back(&s);
unmatched[idn_map ^ 31].pop_back();
}
}
for (const auto& p : to_erase)
std::cout << "will remove element at " << p << 'n';
// now compact over the deferred erasures...
auto erase_it = to_erase.begin();
auto to = stations.begin();
for (auto from = to; from != stations.end(); ++from)
if (erase_it != to_erase.end() && *erase_it == &*from)
++erase_it;
else
*to++ = *from;
stations.erase(to, stations.end());
std::cout << "results:n";
for (const auto& station : stations)
std::cout << station << 'n';
}
代码在这里可用/可运行。
(在我纠正循环逻辑时进行了几次编辑,从使用集合更改为矢量以提高性能)
- 有哪些有效的方法可以消除一组 100 万个字符串>重复数据?
- 在C++中初始化向量映射的最有效方法
- 将此布尔值传递给此函数的最有效方法是什么?
- 找到一种有效的方法,在 2 个巨大的缓冲区上执行 MAX,每字节字节
- 如何在工厂方法中返回指向基于基础操作系统的派生类的有效指针
- 比较C++中两个整数的最有效和最干净的方法是什么?
- 比较C++变量的最有效方法
- C++函子,有什么有效的方法吗?
- 在 c++ 中解决段树以外的范围查询的有效方法是什么?
- 存储变量的更有效方法是什么?
- 确保套装新鲜度的有效方法
- 当映射包含字符串向量作为值时,从值中获取键的有效方法
- 映射唯一值和重复值的有效方法.可以访问键或值的位置
- 在C++事务之间存储大量字符数据的有效方法
- 在unordered_multimap中精确迭代一次每个键的有效方法
- 证明两指针方法有效(对和)
- leetcode中的最大数字:有人能解释为什么这个方法有效吗
- C++ 用指针反向打印数组内容 - 为什么此方法有效
- Makefile:为什么这种自动生成先决条件的方法有效
- g++链接错误-解决方法有效的原因