如何将 std::map 元素从一个减去到另一个并在 C++ 中更新它

how to subtract std::map elements from one to other and update it in C++

本文关键字:另一个 C++ 更新 一个 map std 元素      更新时间:2023-10-16

我试图从同一std::map的所有其他元素中减去std::map的第一个元素。我找不到任何关于这个的东西。可能吗?例如:

std::map<char,int> bar;
bar['a']=11; //should be deleted from other elements
bar['b']=22;
bar['c']=33;
bar['d']=44;
std::cout << "bar contains:n";
for (std::map<char,int>::iterator it=bar.begin(); it!=bar.end(); ++it)
{
  std::cout <<"key: " <<it->first << " Value=> " << it->second << 'n'; //can i delete here??
  //i want to delete value of a from value of b and update the value of b
}
//the new map should be look like as follows
//bar['a']=11; //or may be 0
//bar['b']=11;
//bar['c']=22;
//bar['d']=33;

有什么想法可以用 c++ 中的地图轻松做到这一点吗?谢谢。

C++11 解决方案

您可以使用std::for_each

为此
std::for_each(std::next(bar.begin()), bar.end(), [&bar](std::pair<const char, int>& x){ x.second -= bar.begin()->second; });

例如

#include <algorithm>
#include <iostream>
#include <iterator>
#include <map>
int main()
{
    std::map<char,int> bar;
    bar['a']=11;
    bar['b']=22;
    bar['c']=33;
    bar['d']=44;
    std::for_each(std::next(bar.begin()), bar.end(), [&bar](std::pair<const char, int>& x){ x.second -= bar.begin()->second; });
    std::cout << "bar contains:n";
    for (std::map<char,int>::iterator it=bar.begin(); it!=bar.end(); ++it)
    {
        std::cout << "key: " << it->first << " Value=> " << it->second << 'n';
    }
}

输出(工作演示)

bar contains:
key: a Value=> 11
key: b Value=> 11
key: c Value=> 22
key: d Value=> 33

如果你想从自身中减去第一个元素,只需删除std::next调用并捕获你想要减去的值,因为你要修改第一个映射条目。

auto const sub = bar.begin()->second;
std::for_each(bar.begin(), bar.end(), [&sub](std::pair<const char, int>& x){ x.second -= sub; });

C++03 解决方案

从除第一个元素本身之外的所有元素中减去第一个元素

int value = bar.begin()->second;
std::map<char, int>::iterator it = bar.begin();
std::advance(it, 1);
for (; it != bar.end(); ++it)
{
    it->second -= value;
}

包含第一个元素

int value = bar.begin()->second;
for (std::map<char, int>::iterator it = bar.begin(); it != bar.end(); ++it)
{
    it->second -= value;
}

你只需要遍历映射并从每个元素中减去与"first"键相关的值,将结果存储回同一个元素中。一种方法如下所示:

http://coliru.stacked-crooked.com/a/1bc650592027f5f3 的现场示例

#include <iostream>
#include <map>
int main() {
    // Set up the problem...
    std::map<char, int> foo;
    foo['a'] = 11;
    foo['b'] = 22;
    foo['c'] = 33;
    foo['d'] = 44;
    // Obtain the value of the 'a' key...
    const int value = foo['a'];
    // Subtract that value from each element...
    for (auto& element : foo) {
        element.second -= value;
    }
    // Output the map to verify the result...
    for (auto& element : foo) {
        std::cout << element.first << ": " << element.second << "n";
    }
    return 0;
}

请注意,如果遍历整个地图,则需要存储 foo[a] 的初始值,因为在迭代减法期间将其归零。您可以通过使用迭代器并跳过第一个元素来避免这种情况,例如 std::next(foo.begin()) .其他答案演示了这种技术,所以我不会在这里重复它。

您可以使用在标头<algorithm>中声明的标准算法std::for_each

如果您的编译器支持 C++ 2014,则代码可能如下所示

#include <iostream>
#include <map>
#include <algorithm>
#include <iterator>
int main() 
{
    std::map<char, int> bar;
    bar['a'] = 11;
    bar['b'] = 22;
    bar['c'] = 33;
    bar['d'] = 44;
    for ( const auto &p : bar )
    {
        std::cout << "{ " << p.first << ", " << p.second << " } ";
    }
    std::cout << std::endl;
    if ( !bar.empty() )
    {        
        std::for_each( std::next( bar.begin() ), bar.end(), 
                       [value = ( *bar.begin() ).second] ( auto &p ) { p.second -= value; } );
    }            
    for ( const auto &p : bar )
    {
        std::cout << "{ " << p.first << ", " << p.second << " } ";
    }
    std::cout << std::endl;
}    

程序输出为

{ a, 11 } { b, 22 } { c, 33 } { d, 44 } 
{ a, 11 } { b, 11 } { c, 22 } { d, 33 } 

如果您的编译器仅支持 C++ 2011,则程序中的主循环可能如下所示

if ( !bar.empty() )
{
    auto value = ( *bar.begin() ).second;
    std::for_each( std::next( bar.begin() ), bar.end(), 
                   [value] ( std::pair<const char, int> &p ) { p.second -= value; } );
} 
例如,

使用基于范围的 for 循环也可以完成相同的操作

#include <iostream>
#include <map>
int main() 
{
    std::map<char, int> bar;
    bar['a'] = 11;
    bar['b'] = 22;
    bar['c'] = 33;
    bar['d'] = 44;
    for ( const auto &p : bar )
    {
        std::cout << "{ " << p.first << ", " << p.second << " } ";
    }
    std::cout << std::endl;
    if ( !bar.empty() )
    {        
        auto value = ( *bar.begin() ).second;
        bool first = true;
        for ( auto &p : bar )
        {
            if ( first ) first = !first;
            else p.second -= value;
        }
    }
    for ( const auto &p : bar )
    {
        std::cout << "{ " << p.first << ", " << p.second << " } ";
    }
    std::cout << std::endl;
}    

此外,如果应该减少所有其他元素的元素不是映射的第一个元素,那么您可以使用以下方法

#include <iostream>
#include <map>
#include <algorithm>
#include <iterator>
int main() 
{
    std::map<char, int> bar;
    bar['a'] = 11;
    bar['b'] = 22;
    bar['c'] = 33;
    bar['d'] = 44;
    for ( const auto &p : bar )
    {
        std::cout << "{ " << p.first << ", " << p.second << " } ";
    }
    std::cout << std::endl;
    if ( !bar.empty() )
    {
        // the initializer can be any element not only the first one          
        const auto &value = *bar.begin(); 
        for ( auto &p : bar )
        {
            if ( p.first != value.first  ) p.second -= value.second;
        }
    }
    for ( const auto &p : bar )
    {
        std::cout << "{ " << p.first << ", " << p.second << " } ";
    }
    std::cout << std::endl;
}    
int value = bar.begin()->second;
for(std::map<char,int>::reverse_iterator it=bar.rbegin(); it != bar.rend(); it++) {
    it->second -= bar.begin()->second;
}
bar.begin()->second = value;
相关文章: