我遇到了这个代码段,其中合并了两个向量,其中一个向量的元素在重复的情况下是有利的:
std::vector<String> fields1 = fieldSource1.get();
std::vector<String> fields2 = fieldSource2.get();
// original
fields1.insert(std::end(fields1), std::begin(fields2), std::end(fields2));
std::stable_sort(std::begin(fields1), std::end(fields1));
fields1.erase(std::unique(std::begin(fields1), std::end(fields1)), std::end(fields1));
return fields1;
鉴于字符串在各自的向量中是唯一的,并且输出向量中字符串的顺序是无关紧要的,我认为我可以使这个算法更有效。
我想避免额外的内存分配std :: set_union()和std :: set_diff()。
(由于在调整大小期间迭代器失效,直接将std :: set_diff插入原始向量不是一个选项)
我最终得到了这个,这是std :: set_diff,其中一个迭代器替换为索引:
std::sort(std::begin(fields1), std::end(fields1));
std::sort(std::begin(fields2), std::end(fields2));
// Initialize iterators by index in case of resizing
size_t index = 0;
size_t end = std::size(fields1);
std::remove_copy_if(std::begin(fields2), std::end(fields2), std::back_inserter(fields1),
[&fields1, &index, end](String field)->bool{
auto begin = std::begin(fields1);
found = std::lower_bound(begin+index, begin+end, field);
index = std::distance(begin, found);
return (*found) == field;
});
return fields1;
我的问题是:我可以更有效地进行此合并操作吗?如果没有,我可以让它更具可读性吗?
答案 0 :(得分:0)
如果要将字符串保持为已排序或可合并状态,则将一串字符串表示为向量是低效的。最好使用另一个容器,例如std :: set或std :: unordered_set,它具有更好的性能保证。
请注意,任何尝试对字符串进行排序的解决方案都可能会进一步破坏内存,并且比首先创建正确的数据结构更多地增加内存压力。
如果必须将它们保存为字符串向量,那么您可以考虑创建一个哈希表,其中包含在每个点上看到的所有字符串,然后只允许插入其哈希值尚未被看到的字符串。如果你有大量的重复项,这种方法可能比独立排序每个列表更有效。
typedef std::size_t hash_type;
typedef std::string value_type;
typedef std::vector< value_type > values_type;
typedef std::hash< value_type > value_hash_type;
typedef std::unordered_set< hash_type > hash_set_type;
bool is_new_hash(hash_set_type &hash_set,
const hash_type one_hash
)
{
if (hash_set.find(one_hash) == hash_set.end())
{
hash_set.insert(one_hash);
return true;
}
return false;
}
int main()
{
values_type str1, str2, dest;
str1.push_back("c");
str1.push_back("a");
str1.push_back("b");
str2.push_back("c");
str2.push_back("d");
hash_set_type hash_set;
value_hash_type value_hash;
for (auto &s : str1)
{
if (is_new_hash( hash_set, value_hash( s ) ))
dest.push_back(s);
}
for (auto &s : str2)
{
if (is_new_hash(hash_set, value_hash(s)))
dest.push_back(s);
}
std::sort(dest.begin(), dest.end());
}