查找多个向量之间的公共元素(无整数元素)

Posted

技术标签:

【中文标题】查找多个向量之间的公共元素(无整数元素)【英文标题】:Find common element between multiple vectors (no integer elements) 【发布时间】:2018-09-04 15:24:04 【问题描述】:

是否有一个C++函数可以找到多个向量之间的共同元素?向量元素不是整数(在我的例子中,元素是 QPair 类型)。

理想情况下,该函数将一组向量作为参数(要比较的向量数量可以变化)并返回向量的共同值。我保证了每个向量中没有重复,但是有可能没有共同的元素。

例子:

vec 1 [a,b]      vec 2 [c,d,a,e,h]     vec 3 [i,j,a]

要返回的公共值:

a

【问题讨论】:

是的,用于预排序的集合:en.cppreference.com/w/cpp/algorithm/set_intersection 没有为此内置任何东西,但有一些算法可以提供帮助。这些向量是否已排序? 我仍然不熟悉对非整数/非字符串数组进行排序的概念。但是没有向量没有排序 std::sort 将对具有 的任何类型的容器进行排序 欢迎来到 SO。请注意,QPair 定义了一个 operator<。但是,QPair 是一个模板,您没有提到配对的 first 和 second 的类型。因此,为了正确操作,第一种和第二种类型也必须提供operator< 【参考方案1】:

正如 Richard 在评论中提到的,使用 std::set_intersection() 可以轻松完成交集。前置条件是已排序的容器。

因此,set_intersection() 中的“集合”可以从数学意义上理解——它不限于std::set。也可以使用已排序的std::vector

要对std::vector 进行排序,可以使用std::sort()。在这种情况下,前置条件是元素的可能顺序,即为元素类型定义了operator<

QPair 定义了一个operator<,如果firstsecond 的类型也可以使用,则可以使用它。

由于 OP 没有提及 QPaired 的类型,我选择了 std::stringdouble 作为我的示例 isectQPair.cc

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

#include <QtCore>

int main()

  // prepare sample data
  typedef QPair<std::string, double> Pair;
  Pair
    a("Hello", 1.23),
    b("World", 2.34),
    c("Stack", 3.45),
    d("Overflow", 4.56),
    e("C++11", 5.67),
    f("C++14", 6.78),
    g("C++17", 7.89),
    h("C++20", 8.90),
    i("gin hill", 10.1),
    j("scheff", 0.0);
  std::vector<Pair> vec1( a, b );
  std::vector<Pair> vec2( c, d, a, e, h );
  std::vector<Pair> vec3( i, j, a );
  // sort vectors
  std::sort(vec1.begin(), vec1.end());
  std::sort(vec2.begin(), vec2.end());
  std::sort(vec3.begin(), vec3.end());
  // intersect vectors
  std::vector<Pair> isect12;
  std::set_intersection(
    vec1.begin(), vec1.end(), vec2.begin(), vec2.end(),
    std::back_inserter(isect12));
  std::vector<Pair> isect123;
  std::set_intersection(
    isect12.begin(), isect12.end(), vec3.begin(), vec3.end(),
    std::back_inserter(isect123));
  // report
  const size_t n = isect123.size();
  std::cout << "Intersection contains " << n << " elements"
    << (n ? ':' : '.') << '\n';
  for (size_t i = 0; i < n; ++i) 
    const Pair &entry = isect123[i];
    std::cout << (i + 1) << ".: '" << entry.first
      << "', " << entry.second << '\n';
  
  // done
  return 0;

isectQPair.pro:

SOURCES = isectQPair.cc

Qt = core

在 Windows 10 上的 cygwin 上编译和测试:

$ qmake-qt5 isectQPair.pro

$ make

$ ./isectQPair
Intersection contains 1 elements:
1.: 'Hello', 1.23

$

Live Demo on ideoneQPair替换为std::pair


关于交叉路口的另一个很好的问答可以在这里找到:SO: how to find the intersection of two std::set in C++?。

【讨论】:

【参考方案2】:

您可以将它们放入哈希表并计算出来。一旦你再次找到它们,就撞计数器。如果特定项目的计数器与向量的数量相同,那么您就得到了一个交集。无需对向量对进行预排序、定义弱排序或字符串排序等。

顺势而为:

#include <iostream>
#include <vector>
#include <list>
#include <unordered_map>

using Qpair = uint32_t; // should be std::pair<int, int> or similar
using Qpairs = std::vector<Qpair>;

int intersections(const std::list<Qpairs>& allpairs) 
    std::unordered_map<Qpair, int> m; // element vs counter

    auto count = allpairs.size(); // number of vectors to scan

    for(const auto& pairs: allpairs)  // loop over all vectors
        for (const auto& p : pairs)  // loop over elements in particular vector
            m[p] += 1;                // and count them
        
    

    int total_count = 0; // how many common elements are here
    for (const auto& e : m) 
        if (e.second == count) 
            ++total_count;
            // you could add e.first to output vector as well
        
    
    return total_count;


int main() 
    Qpairs v1 4, 2, 6, 8, 9 ;
    Qpairs v2 1, 3, 8, 9, 4 ;
    Qpairs v3 2, 8, 9, 5, 0 ;

    std::list<Qpairs> l v1, v2, v3 ;

    auto q = intersections(l);

    std::cout << q << '\n';

    return 0;

【讨论】:

以上是关于查找多个向量之间的公共元素(无整数元素)的主要内容,如果未能解决你的问题,请参考以下文章

查找多个数据框列之间的公共元素

Bailian4134 查找最接近的元素二分查找

查找两个字符串向量的交集

01:查找最接近的元素

蓝桥杯 算法训练 ALGO-50 数组查找及替换

13常见算法数组元素的区间查找