簡體   English   中英

std :: map的查找找不到,但是使用手動掃描的map中的元素

[英]std::map's find fails to find, but element in map with manual scan

我正在使用std :: map和一個列表來跟蹤元素和相關分數上的窗口化。 當窗口已滿時,我想從Windows隊列中彈出一個元素並將其從地圖中刪除。 由於可能存在重復項,因此映射會跟蹤窗口中每個元素遇到了多少次。 我還使用了有序映射,以便可以在給定窗口中不斷獲取最小值。

我的問題是,find()在不期望時返回end()。 當我遍歷地圖時,我發現要顯示的元素。 我不想犧牲使用地圖的對數復雜性。

tl; dr:std :: map表示元素不在地圖中。 手動掃描說是的。

[編輯:Bryan Chen的建議修復了該地圖。 謝謝!]

#include <cstdint>
#include <cstdio>
#include <cinttypes>
#include <map>
#include <list>
#include <vector>

#include "util.h"
#include "kmerutil.h"

namespace kpg {

struct elscore_t {
    uint64_t el_, score_;
    INLINE elscore_t(uint64_t el, uint64_t score): el_(el), score_(score) {
        LOG_ASSERT(el == el_);
        LOG_ASSERT(score == score_);
    }
    INLINE elscore_t(): el_(0), score_(0) {}
    inline bool operator <(const elscore_t &other) const {
        return score_ < other.score_ || el_ < other.el_; // Lexicographic is tie-breaker.
    }
    inline bool operator ==(const elscore_t &other) const {
        return score_ == other.score_ && el_ == other.el_; // Lexicographic is tie-breaker.
    }
    std::string to_string() const {
        return std::to_string(el_) + "," + std::to_string(score_);
    }
};

struct esq_t: public std::list<elscore_t> {
};

typedef std::map<elscore_t, unsigned> esmap_t;

class qmap_t {
    // I could make this more efficient by using pointers instead of
    // elscore_t structs.
    // *maybe* TODO
    // Could also easily templatify this module for other windowing tasks.
    esq_t list_;
#if !NDEBUG
public:
    esmap_t map_;
private:
#else
    esmap_t map_;
#endif
    const size_t wsz_;  // window size to keep
    public:
    void add(const elscore_t &el) {
        auto it(map_.upper_bound(el));
        if(it->first == el) ++it->second;
        else map_.emplace(el, 1);
    }
    void del(const elscore_t &el) {
        auto f(map_.find(el));
        if(f == map_.end()) {
            LOG_DEBUG("map failed :(\n");
            for(f = map_.begin(); f != map_.end(); ++f)
                if(f->first == el)
                    break;
        }
        LOG_ASSERT(f != map_.end());
        if(--f->second <= 0)
            map_.erase(f);
    }
    uint64_t next_value(const uint64_t el, const uint64_t score) {
        list_.emplace_back(el, score);
        LOG_ASSERT(list_.back().el_ == el);
        LOG_ASSERT(list_.back().score_ == score);
        add(list_.back());
        if(list_.size() > wsz_) {
            //fprintf(stderr, "list size: %zu. wsz: %zu\n", list_.size(), wsz_);
            //map_.del(list_.front());
            del(list_.front());
            list_.pop_front();
        }
        LOG_ASSERT(list_.size() <= wsz_);
        return list_.size() == wsz_ ? map_.begin()->first.el_: BF;
        // Signal a window that is not filled by 0xFFFFFFFFFFFFFFFF
    }
    qmap_t(size_t wsz): wsz_(wsz) {
    }
    void reset() {
        list_.clear();
        map_.clear();
    }
};

}

這不是有效的嚴格弱排序:

return score_ < other.score_ || el_ < other.el_;

您有elscore_t(0, 1) < elscore_t(1, 0)elscore_t(1, 0) < elscore_t(0, 1)

正如TC在他的回答中指出的那樣,您的operator<是不正確的。

您可以使用std :: tie進行字典比較

return std::tie(score_, el_) < std::tie(other.score_, other.el_);

否則你可以做

if (score_ == other.score_) {
  return el_ < other.el_; // use el_ to compare only if score_ are same
}
return score_ < other.score_;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM