包含按值按值排序地图的键的向量

时间:2017-08-01 16:36:31

标签: c++ sorting dictionary vector

我有一个:

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

3 个答案:

答案 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)

我将在中解决这个问题,因为它比更简单,并且每个主要编译器供应商都有足够的支持来编译:

制作一个指向字符串的向量并保留足够的空间(出于效率原因)。

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]; }
);

中,您可以取消.first.second

for (auto&[key, value]:fNames)
  sorted_strings.push_back( &value );

使用结构化绑定。