std::find_if 个具有重复数据的自定义对象 std::vector

std::find_if on std::vector of custom objects with duplicate data

考虑以下场景:

typedef struct myStruct
{
    int cn;
    std::string dn;
} MyStruct; 

int main()
{
    std::vector<MyStruct> v;
    // fill some data
    ...
    ...
    int c = 1;
    std::vector<MyStruct>::iterator it = std::find_if(v.begin(), v.end(),
                 [c](const MyStruct& m) -> bool { return m.cn == c; });

    // use 'it' to do stuff
}

如果v包含MyStruct个对象,使得成员变量cn在多个条目中具有值c (=1),如何处理这种情况?作为 std::find_if() returns 指向范围中第一个元素的迭代器,其余元素呢?

find_if 找到范围内的第一个元素和 return 的迭代器。对于 find all 你可以写循环,每次都会从 it:

搜索
std::vector<MyStruct>::iterator it = v.begin();
while (it != v.end())
{
    it = std::find_if(it, v.end(),
    [c](const MyStruct& m) -> bool { return m.cn == c; });
    if (it != v.end())
    {
       // process founded item
       ++it;
    }
}

或者您可以对序列进行排序并使用 equal_range 算法,这将 return std::pair 个迭代器。

对于当前的标准库,您必须使用谓词(如果可以使用 C++11/14 则使用 lambda)在 std::find_if 上编写一个循环,或者使用 std::copy_if 来将每个匹配项复制到新序列。

Ranges proposal 可用时(在技术规范和 C++17 中),事情会变得容易得多,例如您将能够编写一个单一的可组合视图和操作链:

#include <range/v3/all.hpp>
#include <iostream>
#include <vector>

using namespace ranges;

int main()
{
    auto const is_even = [](auto x) { return x % 2 == 0; };
    auto const print = [&](auto x) { std::cout << x << ","; return x; };

    std::vector<int> v { 1, 11, 42, 57, 63, 72 };
    v | view::filter(is_even) | action::transform(print); 
}

Live On Coliru (already works with the range-v3 library).