比较它们之间的元素并获取公用值的键

时间:2018-09-26 22:31:45

标签: c++ algorithm key containers matching

我在两个不同的集合中有一对数据,键和值。我需要比较两个集合的值,并创建一个包含值相等的键对的集合。

例如,具有以下数据集:

      Vals
Key Col1 Col2
1    4     5
2    6     9
4    8     4
6    10    10

公共值将是4和10。因此,他的想法是得到一个带有对的新集合,在这种情况下(键col1,键col2){{1,4},{6,6}}

我需要一种最快的方法来执行此操作,每个集合都可以容纳大约100k的数据,而使用for循环进行迭代太慢了,我尝试使用vector。

两个集合不一定都具有相同的键(如map),并且数据可能不是int(我使用二进制数据,并且通常这些键都是int(长整型))。

这是我的示例代码(非常慢的代码):

struct p {
    unsigned long int p1;
    unsigned long int p2;
};

vector<int> table1 = tables1(n); /* bigger n -> more samples */
vector<int> table2 = tables2(n); /* n = 10000 generate 150k per table */

vector<p> common;

for (unsigned long int i = 0;i < table1.size(); i++) {
    for (unsigned long int j = 0; j < table2.size(); j++) {
        if (table1[i] == table2[j]) {common.push_back ({i, j};}
    }
}

是否可以通过地图,设置或某种方式更快地完成此任务? (我从c ++开始)

2 个答案:

答案 0 :(得分:2)

实际上,您比较了它们之间的所有值,并想知道每个集合中该值的键。

在这种情况下,我建议您简单地反转每个映射中的键和值。这将导致以下问题:

      Vals
RevKey1 RevVal1 RevKey2 RevVal2
4       1         5     1
6       2         9     2
8       4         4     4
10      6        10     6

然后,您只需要遍历第一张地图,并在第二张地图中寻找相同的钥匙即可。

map<int,int> col1;
map<int,int> col2;
map<int,pair<int,int>> common ; 
...
for (auto& x: col1) {
    auto y= col2.find(x.first); 
    if (y!=col2.end()) 
        common[x.first]=make_pair(x.second,y->second);
}
cout<<"Result:"<<endl;
for (auto& x:common ) 
    cout << x.first << "<-" << x.second.first << " in col1 and " <<x.second.second << " in col2"<<endl;

Online demo

备注:作为练习,我将反转现有地图中表示的映射关系。如果多个键具有相同的值,我还可以扩展该算法以应对多图。

答案 1 :(得分:0)

以下(非常简单的)代码似乎割了芥末酱:

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

struct p
{
    p (int p1, int p2) : p1 (p1), p2 (p2) { }
    int p1;
    int p2;
};

std::vector<int> table1;
std::vector<int> table2;
std::vector<p> common;

#define N   100000

int main ()
{
    table1.reserve (N);
    table2.reserve (N);

    for (int i = 0; i < N; ++i)
        table1.emplace_back (rand ());

    for (int i = 0; i < N; ++i)
        table2.emplace_back (rand ());

    std::map <int, int> map1;
    for (int i = 0; i < N; ++i)
        map1 [table1 [i]] = i;

    common.reserve (N);

    int n = table2.size();
    for (int i = 0; i < n; i++)
    {
        auto f = map1.find (table2 [i]);
        if (f != map1.end ())
            common.emplace_back (i, f->second);
    }

    for (auto x : common)
       std::cout << x.p1 << ", " << x.p2 << "\n";
}

输出:

12727, 93810
12766, 48493
16044, 71990
43202, 35849
46218, 81007
82512, 70112
98740, 72244

请注意对向量使用reserveemplace_back

Wandbox上运行它

我尝试将N增加到1000000,但它仍然有效。无序(散列)的地图可能会更快。