簡體   English   中英

地圖,成對向量還是兩個向量……?

[英]Map, pair-vector or two vectors…?

我通讀了一些帖子和“ Wiki”,但仍無法確定哪種方法適合我的問題。

我創建了一個名為Sample的類,其中包含一定數量的化合物(可以說這是Nuclide另一類),並且具有一定的相對數量(兩倍)。

因此,類似(pseudo):

class Sample {
    map<Nuclide, double>;
}

如果樣本中有Ba-133Co-60Cs-137核素,則必須在代碼中准確使用這些名稱才能訪問地圖中的這些核素。 但是,我唯一需要做的就是遍歷地圖以執行計算(它們不關心哪個核素),因此,我將使用for循環。 我想在不關注鍵名的情況下進行迭代,因此,我需要為地圖使用迭代器,對嗎?

一個替代方法是vector<pair<Nuclide, double> >

class Sample {
    vector<pair<Nuclide, double> >;
}

或只是兩個獨立的向量

Class Sample {
    vector<Nuclide>;
    vector<double>;
}

而在最后一個選項中,核素與其數量之間的聯系將是“元信息”,僅由相應向量中的位置給出。

由於我缺乏豐富的經驗,因此請提出關於選擇哪種方法的建議。 我想讓所有可用化合物的迭代過程變得輕松快捷,同時保持相應鍵和值的邏輯結構。

PS .:樣本中的compunds數量可能很低(1到5)! PPS .:是否可以通過某些const語句修改最后一個選項,以防止更改並因此保持正確的順序?

如果迭代需要快速,那么您就不需要std::map<...> :它的迭代是一條遍地開花的樹,很快就會變糟。 std::map<...>實際上只有在序列有很多突變並且需要按鍵排序的序列時才是合理的。 如果您有突變但不關心順序std::unordered_map<...>通常是更好的選擇。 不過,兩種地圖都假設您正在按鍵查找事物。 從您的描述來看,我並不是真的如此。

std::vector<...>快速迭代。 但是,它對於查找不是理想的。 如果將其保持有序,則可以使用std::lower_bound()進行std::map<...>類似的查找(即,復雜度也是O(log n) ),但是要努力保持它排序可能會使該選項過於昂貴。 但是,它是用於將一堆被迭代的對象保持在一起的理想容器。

是否需要一個std::vector<std::pair<...>>還是兩個std::vector<...> s取決於您如何訪問元素:如果元素的兩個部分都已綁定要一起訪問,您需要一個std::vector<std::pair<...>>因為這樣可以保留一起訪問的數據。 另一方面,如果您通常僅訪問兩個組件之一,則使用兩個單獨的std::vector<...> s將使迭代速度加快,因為更多的迭代元素適合於高速緩存行,尤其是當它們合理時小如double s。

無論如何,我建議不要將外部結構暴露給外界,而應該提供一個接口,讓您以后可以更改基礎表示形式。 也就是說,為了獲得最大的靈活性,您不想將表示形式烘烤到所有代碼中。 例如,如果您使用訪問器函數對象(以BGL表示 屬性圖或以Eric Niebler的Range Proposal表示投影 )來訪問基於迭代器的元素,而不是訪問元素,則無需觸摸即可更改內部布局任何算法(不過,您都需要重新編譯代碼):

// version using std::vector<std::pair<Nuclide, double> >
// - it would just use std::vector<std::pair<Nuclide, double>::iterator as iterator
auto nuclide_projection = [](Sample::key& key) -> Nuclide& {
    return key.first;
}
auto value_projecton = [](Sample::key& key) -> double {
    return key.second;
}

// version using two std::vectors:
// - it would use an iterator interface to an integer, yielding a std::size_t for *it
struct nuclide_projector {
    std::vector<Nuclide>& nuclides;
    auto operator()(std::size_t index) -> Nuclide& { return nuclides[index]; }
};
constexpr nuclide_projector nuclide_projection;
struct value_projector {
    std::vector<double>& values;
    auto operator()(std::size_t index) -> double& { return values[index]; }
};
constexpr value_projector value_projection;

有了這些就位,例如,僅在它們之上運行並打印它們的算法可能如下所示:

template <typename Iterator>
void print(std::ostream& out, Iterator begin, Iterator end) {
    for (; begin != end; ++begin) {
         out << "nuclide=" << nuclide_projection(*begin) << ' '
             << "value=" << value_projection(*begin) << '\n';
    }
}

兩種表示完全不同,但是訪問它們的算法完全獨立。 這樣,嘗試不同的表示形式也很容易:只需更改表示形式和訪問它的算法的粘合即可。

暫無
暫無

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

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