迭代并删除 std::set 中的元素

发布于 2024-09-11 16:52:43 字数 633 浏览 4 评论 0原文

我有一个 std::set ,我需要删除类似的相邻元素:

DnaSet::const_iterator next = dna_list.begin();
DnaSet::const_iterator actual = next;
++next;

while(next != dna_list.end()) // cycle over pairs, dna_list is the set
{
    if (similar(*actual, *next))
    {
        Dna dna_temp(*actual);  // copy constructor
        dna_list.erase(actual); // erase the old one
        do
        {
           dna_temp.mutate(); // change dna_temp
        } while(!dna_list.insert(dna_temp).second);  // insert dna_temp
    }
    ++actual;
    ++next;
}

有时程序无法从主循环退出。我认为当我删除 dna_list 中的最后一个元素时,就会出现问题。完成这项任务的正确方法是什么?

I have a std::set and I need to erase similar adjacent elements:

DnaSet::const_iterator next = dna_list.begin();
DnaSet::const_iterator actual = next;
++next;

while(next != dna_list.end()) // cycle over pairs, dna_list is the set
{
    if (similar(*actual, *next))
    {
        Dna dna_temp(*actual);  // copy constructor
        dna_list.erase(actual); // erase the old one
        do
        {
           dna_temp.mutate(); // change dna_temp
        } while(!dna_list.insert(dna_temp).second);  // insert dna_temp
    }
    ++actual;
    ++next;
}

Sometimes the program can't exit from the main loop. I think the problem happens when I erase the last element in the dna_list. What's the correct way to do this task?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

酒废 2024-09-18 16:52:43

使用 actual = next 而不是 ++actual

一旦删除 actual,它就是一个无效的迭代器,因此 ++actual 会表现得很奇怪。 next 应保持不变,因此将 actual 分配给 next 应该可以。

Use actual = next rather than ++actual.

Once you erase actual, it is an invalid iterator, so ++actual will behave strangely. next should remain intact, so assigning actual to next should work.

§普罗旺斯的薰衣草 2024-09-18 16:52:43

最好的选择是创建一个使用 similar() 谓词的比较函子。然后您需要做的就是使用该比较函子构造集合,然后就完成了。集合本身会将两个相似的元素视为相同,并且只让第一个元素进入。

struct lt_different {
    bool operator()(int a, int b) {
        return a < b && !similar(a, b);
    }

private:
    bool similar(int a, int b)
    {
        // TODO:when are two elements similar?
        const int EPSILON = 2;
        return abs(a - b) < EPSILON;
    }
};

// ...
set<int> o;  // fill this set with your data

// copy your data to a new set that rejects similar elements
set<int,lt_different> s(o.begin(), o.end(), lt_different());

您可以使用集合 s:插入元素、删除元素、修改元素 - 并且集合本身将确保集合中不存在两个相似的元素。

也就是说,您也可以自己编写算法,即使只是为了替代选择。查看 中的 std::adjacent_find()。它将找到两个连续相同元素的第一次出现;坚持这个立场。找到后,找到从该点开始与这些元素不同的第一个元素。您最终会得到两个迭代器,它们表示一系列连续的相似元素。您可以使用集合的 erase() 方法来删​​除它们,因为它有一个需要两个迭代器的重载。

起泡沫,冲洗,重复整套。

Your best option is to create a comparison functor that uses the similar() predicate. Then all you need to do is construct the set with that comparison functor and you're done. The set itself will see two similar elements as identical and will only let the first one in.

struct lt_different {
    bool operator()(int a, int b) {
        return a < b && !similar(a, b);
    }

private:
    bool similar(int a, int b)
    {
        // TODO:when are two elements similar?
        const int EPSILON = 2;
        return abs(a - b) < EPSILON;
    }
};

// ...
set<int> o;  // fill this set with your data

// copy your data to a new set that rejects similar elements
set<int,lt_different> s(o.begin(), o.end(), lt_different());

You can work with set s: insert elements, remove elements, modify elements -- and the set itself will make sure no two similar elements exist in the set.

That said, you can also write an algorithm yourself, if only for an alternative choice. Take a look at std::adjacent_find() from <algorithm>. It will find the first occurrence of two consecutive identical elements; hold on to that position. With that found, find the first element from that point that is different from these elements. You end up with two iterators that denote a range of consecutive, similar elements. You can use the set's erase() method to remove them, as it has an overload that takes two iterators.

Lather, rinse, repeat for the entire set.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文