找到一种方法将匹配的键和值从映射推回向量

Posted

技术标签:

【中文标题】找到一种方法将匹配的键和值从映射推回向量【英文标题】:Finding a way to push_back matched key and values from a map into vector 【发布时间】:2019-03-13 01:24:07 【问题描述】:

我在 Java 中有与此类似的代码,但让它在 C++ 中工作是另一回事。目前,此功能确实正确找到了密钥并将密钥推到我的向量后面。我想抓住键和它的一对值都被插入到向量的同一个索引中。我已经研究过使用一对作为我的向量,所以它会是(键,一对值),我不确定我是否能够做到。

vector<string> getIfPresentPartOfSpeech(multimap<string, pair<string, string>> dictionary, string name) 
    vector<string> response;
    auto it = dictionary.begin();
    while (it != dictionary.end()) 
        // Check if value of this entry matches with given value
        if (it->second.first == name) 
            // Yes found
            // Push the key in given map
            response.push_back(it->first);
        
        // Go to next entry in map
        it++;
    
    return response;

【问题讨论】:

所以你想返回一个vector&lt;pair&lt;string, pair&lt;string, string&gt;&gt;&gt; 响应应该是什么?你可以为它定义一个结构。你可以只做地图成员的确切类型——pair> 我正在研究定义结构。我考虑过做pair>。也对我的其他选择感到好奇 【参考方案1】:

为您的response 定义一个结构并返回该类型的std::vector

struct Response 
  std::string key;
  std::pair<std::string, std::string> resp_pair;
;

vector<Response> getIfPresentPartOfSpeech(multimap<string, pair<string, string>> dictionary, string name) 
    vector<Response> response;
    auto it = dictionary.begin();
    while (it != dictionary.end()) 
        // Check if value of this entry matches with given value
        if (it->second.first == name) 
            // Yes found
            // Create a Response object
            Response resp;
            resp.key = it->first;
            resp.resp_pair = it->second;
            // Push it in the vector
            response.push_back(resp);
        
        // Go to next entry in map
        it++;
    
    return response;

还可以通过使用emplace_back 而不是push_back 来进一步优化这一点,以避免容器元素的多个副本传递。

【讨论】:

谢谢!那么我需要更新我的原型以反映这一点吗?所以它将是 vector getIfPresentName(multimap> dictionary, string name); @javaNoob 是的,你是对的。 std::vector&lt;std::pair&lt;std::string,std::pair&lt;std::string, std::string&gt;&gt;&gt; 是你可以做到的,但是定义你自己的 struct 是干净整洁的。 看来,一旦我完成了 getIfPresent 函数的前向声明,我就会收到错误 C2903、C3203、C2079 和 C2371。我相信所有这些都与前瞻声明有关。有什么建议吗? @javaNoob 如果没有机会将目光投向真正的源代码,即代码的 MCVE,很难说出警告的含义。我想你正在使用 MSVC。如果您将 Response 结构定义放在头文件中并将该头包含在源文件中,我认为这应该可以在没有编译器警告的情况下工作。同样,为了进一步帮助您,我可能需要一个 MCVE,以便验证您收到的警告。 我明白了,非常感谢所有的帮助!我现在正在尝试头文件,它似乎修复了 99% 的错误。现在从算法和 xutility 中得到一些问题。很可能是由于我的代码的其他部分【参考方案2】:

您可以在&lt;algorithm&gt; 中使用std::copy_if,而无需手动编写显式循环。还要通过(常量)引用传递dictionary,以避免不必要的复制:

#include <algorithm>
#include <map>
#include <utility>
#include <vector>

// You'll need C++14 to use `auto const& kv` in your lambda expression
std::vector<std::pair<const std::string, std::pair<std::string, std::string>>>
getIfPresentPartOfSpeech(
    const std::multimap<std::string, std::pair<std::string, std::string>>&
        dictionary,
    const std::string& name)

    std::vector<
        std::pair<const std::string, std::pair<std::string, std::string>>>
        res;
    std::copy_if(begin(dictionary), end(dictionary), std::back_inserter(res),
                 [&](auto const& kv)  return kv.second.first == name; );
    return res;


//test
int main()

    std::multimap<std::string, std::pair<std::string, std::string>> dictionary
        "first", "abc", "def",
        "second", "123", "456",
        "first", "asdf", "fdas",
        "thrid", "abc", "123",
    ;
    auto res = getIfPresentPartOfSpeech(dictionary, "abc");
    for (auto& x : res)
        std::cout << x.first << " " << x.second.first << " " << x.second.second
                  << "\n";

使用@aep 建议的结构会更清晰。您需要一个额外的转换构造函数才能使用std::copy_if

struct Response 
    std::string key;
    std::pair<std::string, std::string> value;
    // Provide a conversion constructor that convert your `dictionary` multimap
    // key-value pair into a Response object
    Response(const std::pair<const std::string,
                             std::pair<std::string, std::string>>& kv)
    : keykv.first, valuekv.second
    
;

std::vector<Response> getIfPresentPartOfSpeech(
    const std::multimap<std::string, std::pair<std::string, std::string>>&
        dictionary,
    const std::string& name)

    std::vector<Response> res;
    std::copy_if(begin(dictionary), end(dictionary), std::back_inserter(res),
                 [&](auto const& kv)  return kv.second.first == name; );
    return res;

【讨论】:

编辑以反映 OP 的比较。 谢谢!我正在查看您的建议,我很惊讶它可以在这么多行中完成。在我考虑实施自己之前要弄明白这一点 我一直在考虑这些思路,使用一些 typedef 以提高可读性。 @KennyOstrom 你能解释一下我如何解决函数 getIfPresentPartOfSpeech 上的“前向声明”的问题吗?我使用了我熟悉的技术,但在使用结构时似乎可能是一个不同的过程? tntxtnt 发布了答案。它对我来说只需要另外两个包含。标头原型是一样的,只是一个分号而不是 code 部分。

以上是关于找到一种方法将匹配的键和值从映射推回向量的主要内容,如果未能解决你的问题,请参考以下文章

与参数匹配时返回对象的键和值[重复]

将字典的键和值并行传递给函数?

在 Perl 中反转哈希的键和值

如何在scala中将嵌套映射[string,string]作为点分隔的键和值字符串

如何遍历“IDictionary”的键和值?

如何比较两个json文件并在对象中返回不匹配的键和值