【问题标题】:Remove range of elements from QHash从 QHash 中删除元素范围
【发布时间】:2014-09-10 08:56:10
【问题描述】:

我使用 QHash 作为容器,我的任务是删除所有满足谓词的项目。 一开始我想用Erase-remove idiom,结果发现QHash没有删除范围的选项,只有function通过迭代器删除单个元素。

std::unordered_map(在概念上接近 Qt 的 QHash)具有删除范围的 function

这意味着一个问题:为什么 QHash 没有类似的功能,以及如何最好地从 QHash 中删除满足谓词的项目?

【问题讨论】:

  • 你如何定义unordered_map / hash map中的范围
  • @PiotrS。基于他们的迭代器。例如std::unordered_map::iterator
  • 是的,但你如何定义它?满足条件的元素范围 ? unordered_map 中没有类似的东西,结果是实现定义的,因为 unordered_map 中的元素不是有序的(顾名思义)
  • @PiotrS。我知道 unordered_map 中未指定的顺序(对不起,重言式),但如果我们有迭代器,我们可以有基于它们的范围。可以将其传递给 std::unordered_map::erase 函数。但 QHash 没有。为什么?
  • 因为它是无用的,即使使用 unordered_map 也明确指出:(erase) "注意 unordered_map 容器不遵循任何特定顺序来组织其元素,因此范围删除的效果可能不容易预测。”

标签: c++ qt qhash erase-remove-idiom


【解决方案1】:

在 cmets 的基础上,事实证明,erase-remove 习语不适用于 QHash 容器。

因此,鉴于QHash::erase的描述,特别是它没有违反哈希中的项目顺序

与 remove() 和 take() 不同,此函数不会导致 QHash 重新散列其内部数据结构。这意味着它可以在迭代时安全地调用,并且不会影响哈希中项目的顺序。

我们有以下代码来删除满足谓词的元素:

for( auto it = hash.begin(); it != hash.end(); )
{
    if( pred(*it) )
    {
        it = hash.erase(it); 
    } else {
        ++it;
    }
}

【讨论】:

    【解决方案2】:

    接受的答案不起作用,因为它忽略了来自erase() 的返回值,它是哈希中下一项的迭代器。你需要做的;

    QHash<QObject *, int> objectHash;
    QHash<QObject *, int>::iterator i = objectHash.begin();
    while (i != objectHash.end()) {
        if (i.value() == 0) {         // test here
            i = objectHash.erase(i);
        } else {
        ++i;
    }
    

    根据 Qt 文档链接 - 否则您将增加一个无效的迭代器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-16
      • 1970-01-01
      • 2016-12-30
      • 2013-09-18
      相关资源
      最近更新 更多