在 map<string, vector<string>> 中查找具有最多值的键

问题描述

set<string> myFunc (const map<string,vector<string>>& m)

我想返回一组字符串中的所有键,这些键映射了最多的值(如果映射值的数量相同,则为几个键)。我的尝试是:

set<string> ret;
auto max_e = *max_element(m.begin(),m.end(),[] (const pair<string,vector<string>>& m1,const pair<string,vector<string>>& m2) {
    return m1.second.size() < m2.second.size();
  });
ret.insert(max_e.first);
return ret;

从逻辑上讲,这行不通(我认为),因为这只会返回一个具有最高值的键。有什么想法吗?

解决方法

一种方法是迭代两次:

  • 第一个从所有键中获取最大大小。
  • 第二个获取映射到该大小的键。

它应该看起来像:

set <string> myFunc(const map<string,vector<string>>& m) {
    set <string> ret;
    size_t maximumSize = 0;
    for (const auto& e : m) {
        maximumSize = max(maximumSize,e.second.size());
    }
    for (const auto& e : m) {
        if (e.second.size() == maximumSize) {
            ret.insert(e.first);
        }
    }
    return ret;
}
,

除了@a.Li的回答,如果可能的话,你也可以一路优化不少东西。

当然,对地图进行两次迭代可能是解决问题的成本最低且最简单的方法:

using StringMapType = std::map<std::string,std::vector<std::string>>;
using StringMapVectorType = StringMapType::value_type::second_type;

std::set<StringMapType::key_type> findKeys(const StringMapType &stringMap) {
    StringMapVectorType::size_type maximumSize {};
    for (const auto &[key,values] : stringMap)
        maximumSize = std::max(maximumSize,values.size());
    
    std::set<StringMapType::key_type> results {};
    for (const auto &[key,values] : stringMap)
        if (values.size() == maximumSize)
            results.emplace(key);
    
    return results;
}

但是,如果可能,我会推荐以下内容:

  • 如果您对按地图类型对键进行排序不感兴趣,请使用 std::unordered_map,
  • 替换返回值类型(std::setstd::vector,如果您对结果中存储的键的顺序不感兴趣。

对象生命周期特定的优化:

如果应用,代码可能如下所示:

    std::vector<StringMapType::const_iterator> findKeys(const StringMapType &stringMap) {
        StringMapVectorType::size_type maximumSize {};
        for (const auto &[key,values] : stringMap)
            maximumSize = std::max(maximumSize,values.size());
        
        std::vector<StringMapType::const_iterator> results {};
        for (auto iterator = stringMap.cbegin(); iterator != 
             stringMap.cend(); ++iterator)
            if (const auto &values = iterator->second;
                values.size() == maximumSize)
                results.emplace_back(iterator);
        
        return results;
    }

当然,如果您想避免整个问题,您可以在插入时使用自定义比较器对您的值进行排序,或者找到其数组中元素数量最多的条目,然后插入之前的新条目(当然,您必须使用无序映射或其他容器)。

对未来有用的东西: