限制 std::set 的大小

发布于 2024-10-15 12:56:17 字数 214 浏览 2 评论 0原文

我有一个关于 std::set 容器的简短问题。现在我正在使用推回功能喂食我的套装。当然,对于每个push_back,该集合都会变得越来越大。 我只对最新的 30 个左右的元素感兴趣...旧的元素可以删除。所以我的想法是将集合的大小限制为 30 个左右的元素,并通过这样做消除不需要的旧元素。但是,该集默认不支持限制。我可以偶尔检查一下集合的大小并手动删除多余的元素。 有更聪明的方法吗?

问候伦比

I have a short question about the std::set container. Right now I am feeding my set using the pushback function. Of corse the set becomes larger and larger for every push_back.
I am only intrested in the latest 30 elements or so... The older elements can be deleted. So my idea is to limit the size of the set to 30 elements or so and by doing so getting rid of the unwanted older elements. However the set does not support a limit by default. I could check the size of the set once in a while and manually delet the excess elements.
Is there a smarter way ?

Regards Lumpi

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

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

发布评论

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

评论(4

江南月 2024-10-22 12:56:17

作为解决方案,您可以将 set 数据结构封装到一个类中,并在该类中控制元素计数。

As a solution you can encapsulate the set data structure into a class and in that class control the elements count.

枯叶蝶 2024-10-22 12:56:17

您需要自己构建一个 LRU 结构。一种方法是让 std::map 和 std::list 指向彼此的迭代器。也就是说:

struct lru_entry {
    std::list<lru_entry *>::iterator lru_iterator;
    std::map<your_data, lru_entry *>::iterator map_iterator;
};

std::list<lru_entry *> lru;
std::map<your_data, lru_entry *> lookup;

每当您在映射中查找条目时,请将其关联的列表条目移动到列表的开头。当向map添加一个entry时,创建一个新的lru_entry,将其添加到map和list中,并更新lru_entry结构中的迭代器。当查找映射超过 30 个条目时,您可以使用 lru 列表快速查找最旧的条目。

您可以在上一个 stackoverflow 问题中找到有关如何构建 LRU 列表的更多建议。

You'll need to build a LRU structure yourself. One way to do this would be to have a std::map and std::list pointing to each other's iterators. That is:

struct lru_entry {
    std::list<lru_entry *>::iterator lru_iterator;
    std::map<your_data, lru_entry *>::iterator map_iterator;
};

std::list<lru_entry *> lru;
std::map<your_data, lru_entry *> lookup;

Whenever you look up an entry in the map, move its associated list entry to the start of the list. When adding an entry to the map, create a new lru_entry, add it to both map and list, and update the iterators in the lru_entry structure. When the lookup map exceeds 30 entries, you can then use the lru list to quickly find the oldest entry.

You can find more suggestions on how to build a LRU list in this previous stackoverflow question.

网名女生简单气质 2024-10-22 12:56:17

该集合不仅不支持限制,而且也不告诉您元素的年龄。创建一个封装容器的新类。然后,该类可以提供方法来在添加元素或显式时强制执行大小限制。如果删除是根据添加元素的时间完成的(它针对两端的操作进行了优化),那么队列将是理想的选择。

The set not only does not support a limit, it also does not tell you the age of the element. Create a new class that encapsulates a container. That class can then provide methods to enforce the size limit when adding elements or explicitly. A queue would be ideal if removing is done based on when the element was added (it is optimized for operations at both ends).

白鸥掠海 2024-10-22 12:56:17

因为我有时间,所以我会使用一组和一个列表来完成它。该列表仅跟踪最后 n 个插入的元素。还实现了通用擦除。为了获得更好的性能(如果您没有利用集合是有序的这一事实),您可以考虑使用 unordered_set。 (将 include 替换为 include 以及将 std::set 替换为 std::unordered_set< /代码>)

#include <set>
#include <list>
#include <assert.h>

template<typename T>
struct setkeepn {
    std::set<T> mSet;
    std::list<T> mLast;
    void insert(T element) {
        if (mSet.find(element) == mSet.end()) {
            assert(mSet.size() == mLast.size());
            // put your limit of 30 below
            if (mSet.size() >= 2) {
                T extra = mLast.back();
                mSet.erase(extra);
                mLast.pop_back();
            }
            mSet.insert(element);
            mLast.push_front(element);
        }
    }
    void erase(T element)
    {
        typename std::set<T>::iterator lToEraseFromSet = mSet.find(element);
        if (lToEraseFromSet != mSet.end()) {
            // linear on the number of elements.
            typename std::list<T>::iterator lToEraseFromList = std::find(mLast.begin(),mLast.end(), element);
            assert(lToEraseFromList != mLast.end());

            mSet.erase(lToEraseFromSet);
            mLast.erase(lToEraseFromList);
        }
    }
};

int main(int argc, const char * argv[]) {

    setkeepn<int> lTest;
    lTest.insert(1);
    lTest.insert(2);
    lTest.insert(2);
    lTest.insert(3);
    printf("should see 2 3\n");
    for (auto e : lTest.mSet) { // 2,3
        printf("elements: %d\n",e);
    }
    lTest.insert(4);

    lTest.erase(3);
    printf("should see 4\n");
    for (auto e : lTest.mSet) { // 4
        printf("elements: %d\n",e);
    }

    return 0;
}

结果:

should see 2 3
elements: 2
elements: 3
should see 4
elements: 4

Since I had the time, I would do it using a set and a list. The list just keep track of the last n inserted elements. Also implemented a general erase. For better performance (if you are not taking advantage of the fact that set is ordered) you may consider using unordered_set. (replace include <set> with include <unordered_set> as well as std::set with std::unordered_set)

#include <set>
#include <list>
#include <assert.h>

template<typename T>
struct setkeepn {
    std::set<T> mSet;
    std::list<T> mLast;
    void insert(T element) {
        if (mSet.find(element) == mSet.end()) {
            assert(mSet.size() == mLast.size());
            // put your limit of 30 below
            if (mSet.size() >= 2) {
                T extra = mLast.back();
                mSet.erase(extra);
                mLast.pop_back();
            }
            mSet.insert(element);
            mLast.push_front(element);
        }
    }
    void erase(T element)
    {
        typename std::set<T>::iterator lToEraseFromSet = mSet.find(element);
        if (lToEraseFromSet != mSet.end()) {
            // linear on the number of elements.
            typename std::list<T>::iterator lToEraseFromList = std::find(mLast.begin(),mLast.end(), element);
            assert(lToEraseFromList != mLast.end());

            mSet.erase(lToEraseFromSet);
            mLast.erase(lToEraseFromList);
        }
    }
};

int main(int argc, const char * argv[]) {

    setkeepn<int> lTest;
    lTest.insert(1);
    lTest.insert(2);
    lTest.insert(2);
    lTest.insert(3);
    printf("should see 2 3\n");
    for (auto e : lTest.mSet) { // 2,3
        printf("elements: %d\n",e);
    }
    lTest.insert(4);

    lTest.erase(3);
    printf("should see 4\n");
    for (auto e : lTest.mSet) { // 4
        printf("elements: %d\n",e);
    }

    return 0;
}

result:

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