如何按第一个字符串对字符串对的向量进行分组?

Posted

技术标签:

【中文标题】如何按第一个字符串对字符串对的向量进行分组?【英文标题】:How to group a vector of pairs of strings by first string? 【发布时间】:2013-01-08 15:34:34 【问题描述】:

我有一个包含字符串对的向量:

vector<pair<string, string>> list;

我想对具有相同list[n].firstlist[n].second 字符串进行分组

const size_t nbElements = list.size();
for (size_t n = 0; n < nbElements ; n++)

    const string& name = list[n].first;
    const string& type = list[n].second;


考虑这个例子:

(big; table) (normal; chair) (small; computer) (big; door) (small; mouse)

会导致:

(big; table, door) (normal; chair) (small; computer, mouse)

你知道怎么做吗?

【问题讨论】:

@leemes 你的意思是std::multimap,但是,是的,这将是最简单的解决方案。哦等等,你的意思是std::map&lt;std::string,std::vector&lt;std::string&gt;&gt;,是的,应该也可以。 @ChristianRau 哦,当然是std::multimap,而不是map&lt;...,vector...&gt;。对不起;) 【参考方案1】:

您可以使用std::map


例子:

#include <boost/algorithm/string/join.hpp>
#include <boost/format.hpp>

#include <iostream>
#include <map>
#include <vector>

int main() 
    // define original data
    std::vector<std::pair<std::string, std::string> > v = 
            "a", "b", "a", "c", "b", "a", "b", "d", "c", "e";

    // populate map
    std::map<std::string, std::vector<std::string> > grouped;
    for (auto it = v.begin(); it != v.end(); ++it) 
        grouped[(*it).first].push_back((*it).second);
    

    // output        
    for (auto it = grouped.begin(); it != grouped.end(); ++it) 
        std::cout << boost::format("(%s: %s)\n")
                % (*it).first 
                % boost::algorithm::join((*it).second, ", ");
    

The output is:

(a: b, c)
(b: a, d)
(c: e)

注意,这段代码使用了 C++11 的特性(初始化列表、auto 关键字)。看看上面的链接示例是否成功编译。

为了自己编译它,请确保您使用的编译器支持这些功能或将它们替换为适当的 C++03 等效项。

例如,这里是迭代器类型(在上面的代码中使用auto关键字美化了):

// the iterator on the vector `v`
std::vector<std::pair<std::string, std::string> >::iterator it_v;

// the iterator on the map `grouped`
std::map<std::string, std::vector<std::string> >::iterator it_grouped;

【讨论】:

std::multimap 就是为此而生的。 (当然你的解决方案也可以) @leemes 我认为这更像是将多个值存储到一个键而不是存储具有相同键的多个条目。对于某些任务,我发现多图有点麻烦。 我得到错误 (auto it = result.begin(); it != result.end(); ++it) -- 错误 C4430: 缺少类型说明符 - 假定为 int。注意:C++ 不支持 default-int -- 错误 C2440: 'initializing' : cannot convert from 'std::_Vector_iterator<_ty>' to 'int' @tchike 这个代码利用了 C++11 的特性(初始化列表,auto 关键字)。确保您使用的编译器支持它们或将它们替换为适当的迭代器类型。 @moooeeeeep 我明白了,但我无法让它工作。请问可以更换吗?谢谢。【参考方案2】:

您可能需要多张地图。

std::multimap<std::string, std::string> items;
items.insert("Big", "Chair");
items.insert("Big", "Table");
items.insert("Small", "Person");


for(auto i = items.begin(); i!=items.end; i++)

  std::cout<<"["<<i->first<<" , "<<i->second<<"]"<<std::endl;

输出:

[Big, Chair]
[Big, Table]
[Small, Person]

【讨论】:

以上是关于如何按第一个字符串对字符串对的向量进行分组?的主要内容,如果未能解决你的问题,请参考以下文章

如何编写一个函数将字符向量转换为其元素唯一对的字符向量?

按嵌套 tibble 中作为字符串向量给出的变量对 tibble 进行分组

键值对的聚类

使用 itertools 按第二个值对连续元组进行分组

按第一项对嵌套列表进行排序——itemgetter 没有做到这一点

C ++ - 同时对一对向量的第一个和第二个进行排序