【问题标题】:How to count the equal elements of 2 different vectors in c++?如何计算c ++中2个不同向量的相等元素?
【发布时间】:2019-11-24 00:50:57
【问题描述】:

我正在尝试找到一种方法来计算 C++ 中 2 个相同大小的不同向量中有多少元素相等。向量包含结构,我想通过示例中显示的结构的双变量来比较相等性。

并且说清楚。我不想检查 2 个向量是否相等,而只想计算它们的元素有多少。

以下不起作用。它给出地址而不是值。此外,如果我尝试访问像 pointsA[j].dist 这样的 dist 变量,我会收到错误消息。

vector<struct PointWithDistance*> pointsA, pointsB;

//the struct
struct PointWithDistance {
    Point *p;
    double dist;
};

for (int j = 0; j < k; j++){
    if (pointsA[j] == pointsB[j])
        equalCount++;
}

【问题讨论】:

  • 这是一个指针,所以 pointsA[j]->dist

标签: c++ vector struct count equality


【解决方案1】:
vector<struct PointWithDistance*> pointsA, pointsB;

您的意思是使用指针吗?如果是这样,您必须执行 *(points[A])(和 b),因为您当前的比较比较的是 指针,而不是它们的内容。

另外,结构Point 是否有operator == 以便可以对类型进行比较??

你想强制相同的位置吗?比如说,一个向量{1,2,3} 和一个向量{2,3,4} 通过你的算法将有0 个项目相等,你想要吗?如果不是,则循环第一个向量并在第二个向量的每个元素上使用std::find(或std::upper_bound,如果该向量已排序)。

一些快速代码:

template <typename T=int> struct Point
{
 T x,y;
 bool operator==(const T& t) { return (x == t.x && y == t.y); }
};

std::vector<Point<>> p1 = {1,2,3}; 
std::vector<Point<>> p2 = {2,3,4}; 
for(auto& p : p1)
{
   if (std::find(p2.begin(),p2.end(),p) != p2.end())   
   {
    // similar++;
   }
}

// or
assert(p1.size() == p2.size());
for(size_t i1 = 0 ; i1 < p1.size() ; i1++)
{
    if (p1[i1] == p2[i1]) 
    {
    // equal++;
    }
}

【讨论】:

    【解决方案2】:

    计算 2 个容器中的重复项数量的通用解决方案可能如下所示。如果在容器中找到元素,则使用 std::transform_reduce 添加 (std::plus&lt;&gt;{}) 布尔结果。注意它如何接受两种不同类型的容器,只要它们包含的类型保持不变(例如std::vector&lt;int&gt;std::set&lt;int&gt;)。容器的长度不必相等。有两种 SFINAE 实现可以区分 T 是指针和不是指针的情况:

    #include <algorithm>   //std::find, std::find_if
    #include <cstddef>     //std::size_t
    #include <functional>  //std::plus, 
    #include <iterator>    //std::cbegin, std::cend
    #include <numeric>     //std::transform_reduce
    #include <type_traits> //std::enable_if_t, std::is_pointer_v
    
    namespace {
        //core implementation for duplicate_count
        template<class C, class F>
        std::size_t duplicate_count_impl(const C& container, F pred) {
            return std::transform_reduce(std::cbegin(container), std::cend(container), std::size_t{}, std::plus<>{}, pred);
        }
    }
    
    //returns the number of duplicates in two (different) containers.
    //overload for containers where T is a pointer type.
    template<typename T, template <typename...> class C1, template <typename...> class C2, std::enable_if_t<std::is_pointer_v<T>>* = nullptr>
    std::size_t duplicate_count(const C1<T>& a, const C2<T> &b) {
        return duplicate_count_impl(b, [&](T ptr_b) -> bool {
            return std::find_if(std::cbegin(a), std::cend(a), [&](T ptr_a) -> bool {
                return *ptr_a == *ptr_b;
            }) != std::cend(a);
        });
    }
    
    //returns the number of duplicates in two (different) containers.
    //overload for containers where T is not a pointer type.
    template<typename T, template <typename...> class C1, template <typename...> class C2, std::enable_if_t<!std::is_pointer_v<T>>* = nullptr>
    std::size_t duplicate_count(const C1<T>& a, const C2<T> &b) {
        return duplicate_count_impl(b, [&](T n) -> bool {
            return std::find(std::cbegin(a), std::cend(a), n) != std::cend(a);
        });
    }
    

    #include <iostream>
    #include <vector>
    #include <list>
    
    //[duplicate_count implementations]
    
    struct Point {
        int a, b;
    
        bool operator==(const Point& other) const {
            return this->a == a && this->b == other.b;
        }
    };
    
    int main() {
        {
            std::list<int> v = { 1, 2, 7, 7 };
            std::list<int> u = { 0, 1, 2, 7 };
            std::cout << "list<int>\t number of duplicates: " << duplicate_count(v, u) << '\n';
        }
    
        {
            auto[a, b, c, d] = std::make_tuple(0, 1, 2, 3);
            std::vector<int*> v = { &b, &c, &d, &d };
            std::vector<int*> u = { &a, &b, &c, &d };
            std::cout << "vector<int*>\t number of duplicates: " << duplicate_count(v, u) << '\n';
        }
    
        {
            auto[a, b, c, d] = std::make_tuple(
                Point{ 0, 0 }, 
                Point{ 1, 1 },
                Point{ 2, 2 }, 
                Point{ 4, 4 });
    
            std::vector<Point*> v = { &b, &c, &d, &d };
            std::vector<Point*> u = { &a, &b, &c, &d };
            std::cout << "vector<Point*>\t number of duplicates: " << duplicate_count(v, u) << '\n';
        }
    }
    
    list<int>        number of duplicates: 3
    vector<int*>     number of duplicates: 3
    vector<Point*>   number of duplicates: 3
    

    【讨论】:

    • 很好......但是 OP 的(伪)代码表明他/她正在寻找具有相同索引的元素相等的次数。这些模板似乎也在寻找两组中重复的总数。
    【解决方案3】:

    您展示的解决方案很好、快速且高效。

    它有一些很容易解决的小问题。在您的定义 vector&lt;struct PointWithDistance*&gt; pointsA, pointsB; 中,变量 pointsA 和 pointsB 是向量,包含指向结构的指针。

    使用 pointsA[n] 你会得到一个指向结构的指针。但是你想要结构本身。所以你只需要取消引用得到的指针。并且由于您想要访问结构的成员(通常使用 variable.member 完成),您可以使用 (*(pointsA[j])).dist 或 pointsA[j]->dist。

    如果保证向量的大小相同,则只需将代码更新为

    vector<struct PointWithDistance*> pointsA, pointsB;
    
    //the struct
    struct PointWithDistance {
        Point *p;
        double dist;
    };
    
    for (int j = 0; j < k; j++){
        if (pointsA[j]->dist == pointsB[j]->dist)
            equalCount++;
    }
    

    这是你唯一缺少的东西。

    【讨论】:

      【解决方案4】:

      你可以使用std::inner_product算法:

      #include <iostream>
      #include <numeric>
      #include <vector>
      
      int main () {
         const std::vector a{7, 7, 7, 7};
         const std::vector b{7, 6, 7, 7};
      
         const auto equalCount = std::inner_product(
            a.begin(), a.end(), b.begin(), 0,
            std::plus<>(), std::equal_to<>()
         );
      
         std::cout << equalCount << " of the elements are equal.\n";
      }
      

      输出

      3 of the elements are equal.
      

      它是标准内积的概括, 使用函数 + (plus) 和 == (equal_to), 而不是+*。 因此它计算 0 + (a[0] == b[0]) + (a[1] == b[1]) + ....

      这利用了false/true可以解释为0/1这一事实。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-18
        • 1970-01-01
        • 2022-11-22
        • 2019-06-02
        相关资源
        最近更新 更多