c++ - 将键值内容从第一张图移到第二张(值键)图的正确方法是什么?

标签 c++ dictionary move-semantics

我正在尝试计算文本中最常见的单词,因此首先我填充了的 map ,其次我正在尝试将 map 的内容移动到multimap 。但是存在问题:STL映射/哈希的节点类型为。我试图const_cast,它起作用了,但是看起来很丑,很丑。还有其他移动内容的方法吗?

int main()
{
    std::unordered_map<std::string, std::size_t> words;
    std::multimap<std::size_t, std::string> sorted_ordered_words;

    std::for_each(std::istream_iterator<std::string>{std::cin}, {}, [&](const std::string& str)
    {
        ++words[str];
    });

    std::transform(std::make_move_iterator(std::begin(words)),
                    std::make_move_iterator(std::end(words)),
                    std::inserter(sorted_ordered_words, std::end(sorted_ordered_words)),
                    [](decltype (words)::value_type && v)
    {
        return std::make_pair(v.second, std::move(const_cast<std::string&>(v.first)));
    });
    for (const auto &[count, word] : sorted_ordered_words)
    {
        std::cout << count << " - " << word << std::endl;
    }
    return 0;
}

最佳答案

将字符串从原始容器中移出的一种明确定义的方法是将其首先位于的节点移到extract。这暴露了对键的非常量引用。

for (auto it = words.begin(); it != words.end();) {
    auto copy = it;
    ++it;

    auto node = words.extract(copy);

    static_assert(std::is_same_v<decltype(std::move(node.key())), std::string&&>);
    sorted_ordered_words.emplace(node.mapped(), std::move(node.key()));
}
使用const_cast绝对是UB,因为键只是从中移出但仍在 map 上,这违反了内部约束(所有字符串都是相同的"",当它们都应该唯一时)。例如,这可能导致析构函数崩溃。

如果仅用于顺序打印,则无需构建多图。只对成对的 vector 排序要比逐个插入多图更快。
std::vector<decltype(words)::value_type*> vec;
vec.reserve(words.size());
std::transform(words.begin(), words.end(), std::back_inserter(vec), [](auto& v) { return &v; });
std::sort(vec.begin(), vec.end(), [](auto* l, auto* r) {
    return l->second < r->second;
});


for (const auto* item : vec) {
    const auto& [word, count] = *item;
    std::cout << count << " - " << word << std::endl;
}
您还可以使用std::vector<std::pair<std::size_t, const std::string&>>并按.first进行排序。

关于c++ - 将键值内容从第一张图移到第二张(值键)图的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64498089/

相关文章:

c++ - C++11 编译器何时会使 RVO 和 NRVO 优于 move 语义和 const 引用绑定(bind)?

c++ - 在源文件中定义方法时出错

C++ vector<vector<double>> 加倍 **

python - 来自列表中字典的字典的数据框

Python嵌套结构

c++ - QPainter怎么转? (从工厂函数中 move 一个对象)

c++ - 具有指针数据类型的非类型函数模板参数

c++ - 需要一些解密 opencv 线角度

python - 实现 group_by_owners 字典

c++ - 从类中返回可 move 的成员变量