map<T,Z> m= ...;
vector<T> v;
v.reserve(m.size);
for(map<T,Z>::iterator it=m.begin();it!=m.end();++it)
{
v.push_back(it->first);
}
有沒有使用一些STL功能的一個更好的1行版本?使用STL從地圖填充矢量<T><T,Z>的鑰匙
編輯:不是使用C++ 11!
map<T,Z> m= ...;
vector<T> v;
v.reserve(m.size);
for(map<T,Z>::iterator it=m.begin();it!=m.end();++it)
{
v.push_back(it->first);
}
有沒有使用一些STL功能的一個更好的1行版本?使用STL從地圖填充矢量<T><T,Z>的鑰匙
編輯:不是使用C++ 11!
便攜:
struct SelectKey {
template <typename F, typename S>
F operator()(const std::pair<const F, S> &x) const { return x.first; }
};
std::transform(m.cbegin(), m.cend(), std::back_inserter(v), SelectKey());
我認爲STL的一些實現有一個非標準擴展名爲select1st
,這是這裏顯示的SelectKey
相當。正如K-Ballo在評論中指出的那樣,還有一個TR1版本。我喜歡這個明確命名的版本,因爲它更容易看到發生了什麼。
由於沒有必要的狀態,您可以通過使用一個實際的功能,而不是一個函子逃脫略少的樣板:
template <typename F, typename S>
F SelectKey()(const std::pair<const F, S> &x) { return x.first; }
std::transform(m.cbegin(), m.cend(), std::back_inserter(v), SelectKey);
如果你可以用C++ 11,你可以使用拉姆達,這使選擇代碼接近它的使用,其中:
std::transform(m.cbegin(), m.cend(), std::back_inserter(v),
[](const std::pair<const F, S> &x) { return x.first; });
甚至範圍爲基礎的循環,這可能是最優雅和可讀性:
for(const auto &x : m) {
v.push_back(x.first);
}
在C++ 11,你可以使用lambda表達式:
typedef std::map< std::string, std::string > map_t;
map_t map;
std::vector<std::string> v;
std::for_each(map.begin(), map.end(), [&v](map_t::value_type const& it)
{
v.push_back(it.first);
});
預C++ 11,你可以使用轉換和自定義功能結構:
template <class K, class V>
struct key_selector : std::unary_function<const std::pair<K, V>&, const K&>
{
const K& operator()(const std::pair<K, V>& element) const
{
return element.first;
}
};
transform(m.begin(), m.end(), back_inserter(v), key_selector<T,Z>());
如果你有進入升壓或TR1,您可以將其替換key_selector
mem_fn
transform(m.begin(), m.end(), back_inserter(v), mem_fn(&map<T,Z>::value_type::first));
後C++ 11,你可以使用lambda表達式:
transform(m.begin(), m.end(), back_inserter(v), [](const map<T,Z>::value_type& x) {return x.first;});
在pre C++ 11中,你不能使用'bind'。如果你依賴非標準的擴展或提升,那就這麼說吧。 –
@Christian:真的,與預C++ 11你可以使用'std :: tr1 :: bind'的警告。 – ildjarn
@ildjarn是的,但他應該這樣說,而不是假裝它是標準的。 –
你可以做線沿線的東西:
std::transform(m.begin(), m.end(), std::back_inserter(v), FUNCTOR);
凡函子依賴於STL或庫,並且您有編譯器的版本。
C++ 11(拉姆達)
std::transform(m.begin(), m.end(), std::back_inserter(v), [](map<T,Z>::const_reference a) { return a.first; });
C++ 11(STD ::得到)
std::transform(m.begin(), m.end(), std::back_inserter(v), &std::get<0>);
C++ SGI STL具有仿函數稱爲select1st可用於
std::transform(m.begin(), m.end(), std::back_inserter(v), select1st);
使用像其他人一樣的函子對象描述了C++ 03(Not C++ 11)。
矯枉過正?無論如何,你並沒有輸入太多的代碼來實現這一點。 –
@Als:通過這個邏輯,很多std ::算法同樣沒用。 –
@Mahesh - 我正在考慮一些後插入魔法,或者其他什麼 –