【问题标题】:Find and replace elements from a vector by value按值从向量中查找和替换元素
【发布时间】:2018-07-12 11:40:24
【问题描述】:

我有一个包含不同组数据的向量。如果我将特定组的新数据插入向量中,它应该用相同组号的新数据替换旧数据。对于这个特定的例子,std::replace 给出了一个错误

std::replace: 找不到匹配的重载函数

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

class data
{
    public:
        int group;
        bool condition;
        friend bool operator==(const data& lhs, const data& rhs);
        data(int g, bool c) 
        {
            group = g;
            condition = c;
        }
};

bool  operator==(const data& lhs, const data& rhs)
{
     return lhs.group == rhs.group;
}

int main()
{
    data info_1(1, true);
    data info_2(2, true);
    data info_3(3, false);
    data info_4(4, false);
    data info_5(3, false); 

    std::vector<data> data_vector;

    data_vector.push_back(info_1);
    data_vector.push_back(info_2);
    data_vector.push_back(info_3);
    data_vector.push_back(info_4);

    if (std::find(data_vector.begin(), data_vector.end(), info_5) != data_vector.end())
    {
        std::cout << " Matched: \n";
        std::replace(data_vector.begin(), data_vector.end(), data_vector, info_5);
    }
    else
    {
        std::cout << "Not Matched: \n";
    }

    system("pause");

    return 0;
}

【问题讨论】:

  • 也许std::vector 不是正确的容器类型?也许你应该使用例如std::unordered_set(具有合适的 std::hash 专业化)?
  • @Someprogrammerdude,或者可能是 std::map ?有什么取舍吗?
  • std::replace - 第三个参数是一元谓词或比较值 (see here) 而不是 std::vector 对象。
  • std::unordered_map... 此处的地图(有序或无序)可能会更好,因为您可以将group 作为键,将数据作为数据。跨度>

标签: c++ vector


【解决方案1】:

这是您的代码的修改版本。您应该使用迭代器来获取 find() 返回的内容,如果它有效,则将其传递给 replace() -

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

class data
{
    public:
        int group;
        bool condition;
        friend bool operator==(const data& lhs, const data& rhs);
        data(int g, bool c) 
        {
            group = g;
            condition = c;
        }
};

bool  operator==(const data& lhs, const data& rhs)
{
     return lhs.group == rhs.group;
}

int main()
{
    data info_1(1, true);
    data info_2(2, true);
    data info_3(3, false);
    data info_4(4, false);
    data info_5(3, false); 

    std::vector<data> data_vector;

    data_vector.push_back(info_1);
    data_vector.push_back(info_2);
    data_vector.push_back(info_3);
    data_vector.push_back(info_4);

    std::vector<data>::iterator it = std::find(data_vector.begin(), data_vector.end(), info_5);

    if ( it != data_vector.end())
    {
        std::cout << " Matched: " << info_5.group << std::endl;
        std::replace(data_vector.begin(), data_vector.end(), *it, info_5);
    }
    else
    {
        std::cout << "Not Matched: \n";
    }

    system("pause");

    return 0;
}

【讨论】:

    【解决方案2】:

    你想多了。 std::replace 正是你想要的:

    std::replace(data_vector.begin(), data_vector.end(), info_5, info_5);
    

    这看起来有点奇怪,因为它将info_5 替换为info_5,但这是因为operator== 对于这种类型有点奇怪——它只查看组值,所以它会找到info_3 并将其替换为 info_5

    现在,这可能有点过头了,因为它会在向量中查找每个出现的info_5 并将它们全部替换。在许多情况下,只有一个匹配值;您可以使用std::find 找到它,然后分配一个新值:

    auto iter = std::find(data_vector.begin(), data_vector.end(), info_5);
    if (iter != data_vector.end())
        *iter = replacement_value;
    

    另一方面,如果您真的只希望每个组有一个条目,您最好使用std::map。要替换与关联的,只需查找组并分配给它。使用类型为 std::map&lt;int, bool&gt; 的名为 data_map 的对象并为其分配了值,您需要做的就是:

    data_map[3] = false;
    

    但是,如果没有包含 3 个组的条目,则会添加一个。如果这不是您想要的,您必须先检查:

    auto iter = data_map.find(3);
    if (iter != data_map.end())
        *iter = replacement_value;
    

    【讨论】:

    • 谢谢!很有帮助。
    • @ZeeshanHayat - 您通常应该等待一天左右才能接受答案。有人可能会写一个更好的;例如,我没有提到std::set,它比std::map 更适合您的data 类,因为它会以不变的方式处理它,并且可能更适合。
    【解决方案3】:

    我建议您使用 std::map 来达到您的目的。

    #include <iostream>
    #include <map>
    #include <algorithm>
    
    void insert_or_assign (std::map<int, bool> &data, const std::pair <int, bool> item){
        auto search = data.find(item.first);
        if(search != data.end()) {
            data.erase(search);
        }
        data.insert(item);
    }
    
    int main() {
        std::map<int, bool> data;
    
        data.insert(std::pair <int, bool> (1, true));
        data.insert(std::pair <int, bool> (2, true));
        data.insert(std::pair <int, bool> (3, true));
        data.insert(std::pair <int, bool> (4, false));
        data.insert(std::pair <int, bool> (5, false));
    
         insert_or_assign(data, std::pair <int, bool> (5, true));
         insert_or_assign(data, std::pair <int, bool> (6, true));
    
        for (const auto &item : data) {
           std::cout << item.first << " " <<item.second << "\n";
        }
    }
    

    这给出了输出

    1 1
    2 1
    3 1
    4 0
    5 1
    6 1
    

    如果你有c++17编译器可以直接使用std::map::insert_or_assign

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-04
      • 1970-01-01
      • 2016-08-16
      • 2020-08-20
      • 1970-01-01
      • 1970-01-01
      • 2023-01-31
      • 2014-11-20
      相关资源
      最近更新 更多