我有一个:
std::map<long, std::wstring> fNames; // ex: fNames[FileReferenceNumber] = L"hello.txt"
由于std::map
已订购密钥,但不是值(哈希表unordered_map
甚至没有订购),我想创建一个向量:
std::vector<long> v;
包含键以允许fNames
的迭代按值排序。
示例:如果我们有
9187 =&gt; &#34; hello.txt的&#34;
13 =&gt; &#34; z.txt&#34;
1777 =&gt; &#34; A.TXT&#34;
然后v
将是:[1777, 9187, 13]
,允许按值fNames
进行迭代:
for (int i = 0; i < v.size(); i++)
wcout << fNames[v[i]]; // a.txt, hello.txt, z.txt
有没有办法使用v
创建此向量std::sort
?我不知道怎么做。我应该使用自定义谓词吗?
PS:更好:是否可以生成std::vector<wstring> w
排序?即每个元素w[0]
,w[1]
等都包含一个&#34;链接&#34; (指针?)到fNames
的wstrings,但不是副本(以避免重复字符串数据)?
或者它可能是std::vector<wchar_t *> w
?
答案 0 :(得分:1)
使用指向地图元素的指针向量,并对这些指针进行排序。这使您可以访问long和wstrings,而无需复制。
using value_type = std::map<long, std::wstring>::value_type;
std::vector<value_type*> v;
for (auto& e : fNames)
v.push_back(&e);
auto compare_by_second = [](value_type* lhs, value_type* rhs) {
return lhs->second < rhs->second;
};
std::sort(v.begin(), v.end(), compare_by_second);
现在,您可以通过wstring
访问v[N]->second
值,通过v[N]->first
访问长值。
Pre-C ++ 11 version
bool compare_by_second(std::pair<const long, std::wstring>* lhs,
std::pair<const long, std::wstring>* rhs)
{
return lhs->second < rhs->second;
}
// in some function
std::map<long, std::wstring> fNames;
...
std::vector<std::pair<const long, std::wstring>*> v;
for (std::map<long, std::wstring>::iterator b = fNames.begin();
b != fNames.end(); ++b)
{
v.push_back(&*b);
}
std::sort(v.begin(), v.end(), compare_by_second);
如果你只需要字符串而不需要long,那么你可以使用指向字符串的向量来代替。
bool deref_compare(std::wstring* lhs, std::wstring* rhs)
{
return *lhs < *rhs;
}
// in some function
std::map<long, std::wstring> fNames;
...
std::vector<std::wstring*> v;
for (std::map<long, std::wstring>::iterator b = fNames.begin();
b != fNames.end(); ++b)
{
v.push_back(&b->second);
}
std::sort(v.begin(), v.end(), deref_compare);
答案 1 :(得分:1)
PS:更好:是否有可能产生一个std::vector<wstring> w
已排序?即每个元素w[0]
,w[1]
等。 将包含一个&#34;链接&#34; (指针?)到fNames
&#39;wstring
s,但不是副本 (为避免重复字符串数据)?
vector<wstring>
将包含字符串的重复项(因为CW 11,因为CoW - 写入时复制 - 已被std::[w]string
禁止)。如果您想使用const wchar_t*
来避免字符串重复,您可以执行以下操作:
vector<const wchar_t*> sortedFilenames;
// Reserve room in the vector, since we know how many strings to add
sortedFilenames.reserve(fNames.size());
// Add string pointers from map to vector
for (const auto& e : fNames) {
// Avoid duplicates using const wchar_t*
sortedFilenames.push_back(e.second.c_str());
}
// Sort the string vector
sort(begin(sortedFilenames), end(sortedFilenames),
[](const auto& p1, const auto& p2) {
// Use whatever sorting rule you need here...
return wcscmp(p1, p2) < 0;
}
);
编辑根据您的评论,您也可以使用vector<const wstring*>
,例如:
vector<const wstring*> sortedFilenames;
// Reserve room in the vector, since we know how many strings to add
sortedFilenames.reserve(fNames.size());
// Add string pointers from map to vector
for (const auto& e : fNames) {
sortedFilenames.push_back(&(e.second));
}
// Sort the string vector
sort(begin(sortedFilenames), end(sortedFilenames),
[](const auto& p1, const auto& p2) {
return (*p1) < (*p2); // or whatever sorting rule...
}
);
答案 2 :(得分:1)
我将在c++14中解决这个问题,因为它比c++11或c++03更简单,并且每个主要编译器供应商都有足够的支持来编译:
制作一个指向字符串的向量并保留足够的空间(出于效率原因)。
std::vector<std::wstring const*> sorted_strings;
sorted_strings.reserve(fNames.size());
填充指针:
for (auto& entry:fNames)
sorted_strings.push_back( &entry.second );
对它们进行排序:
std::sort(
begin(sorted_strings), end(sorted_strings),
[](auto* lhs, auto* rhs) { return *lhs < *rhs; }
);
用于键矢量:
std::vector<int> sorted_keys;
sorted_keys.reserve(fNames.size());
for (auto&& entry:fNames)
sorted_strings.push_back( entry.first );
std::sort(
begin(sorted_keys), end(sorted_keys),
[&](int lhs, int rhs) { return fNames[lhs] < fNames[rhs]; }
);
在c++17中,您可以取消.first
和.second
:
for (auto&[key, value]:fNames)
sorted_strings.push_back( &value );
使用结构化绑定。