繁体   English   中英

如何在地图中使用带有lambda函数的tolower? C ++

[英]How to use tolower with lambda function in map? C++

我想将存储在地图中的所有单词更改为小写。 使用lambda函数和变换,该怎么办?

std::map <string, int> M;
std::map<string, int> M1;

std::transform(M.begin(), M.end(), M1.begin(),
         [](pair<const string, int> const & p) { ::tolower(p.first); });

您无法编辑map ,因此您必须创建一个新地图

类似于以下内容:

  • 遍历地图中的值
  • 取得钥匙的副本
  • 转换为小写
  • 其插入结果图:

例:

#include <iostream>
#include <map>
#include <algorithm>

int main()
{
    std::map<std::string, int> map = {{ "HELLO", 1 }, { "WORLD", 2 }};

    std::cout << "before:\n";
    for (auto& kv : map)
    {
        std::cout << '\t' << kv.first << ":" << kv.second << '\n';
    }

    // create a new map with lowercase keys
    std::map<std::string, int> out;
    std::for_each(map.begin(), map.end(), [&](auto& kv)
        {
            std::string lower;
            std::transform(kv.first.begin(), kv.first.end(), std::back_inserter(lower), tolower);
            out[lower] = kv.second;
        });

    std::cout << "after:\n";
    for (auto& kv : out)
    {
        std::cout << '\t' << kv.first << ":" << kv.second << '\n';
    }

    return 0;
}

输出:

before:
    HELLO:1
    WORLD:2
after:
    hello:1
    world:2

std::transform将函子的结果分配给目标范围内的元素。 这意味着目标迭代器必须是范围的开始,且范围必须与输入范围相同。 在您的示例中,目的地是一个空地图。 转换本质上是以下循环:

std::map <string, int> M;
std::map<string, int> M1;

for(auto i=M.begin(), j=M1.begin(); i != M.end(); ++i,++j)
{
    *j = f(*i);
}

对于空容器,递减j是非法的,并且对于映射实际上没有任何意义,因为您无法更改键。

您可以从此代码中看到,您的lambda也不正确。 它应该将一对(键值)对转换为目标类型的对象。 在您的情况下,目标类型是相同的。

您要么必须在此之前调整目标容器的大小,例如通过调用resize如果它是一个矢量),或者使用迭代器将其分配调整为map::insert STL为此提供了适配器:

#include <map>
#include <string>
#include <cctype>
#include <iterator>
#include <algorithm>

int main() {
std::map <std::string, int> M;
std::map<std::string, int> M1;

std::transform(M.begin(), M.end(), std::inserter(M1, M1.begin()),
               [](std::pair<const std::string, int> const & p) 
{ 
    std::string lowercase;
    std::transform( p.first.begin(), p.first.end(), 
                    std::back_inserter(lowercase),
                    [](auto c) {return std::tolower(c);} );

    return std::make_pair(lowercase, p.second); 
});

return 0;
}

如果您想使用完全std::transform则可以使用以下方法

#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include <cctype>
#include <iterator>
#include <utility>


int main ()
{
    std::map<std::string, int> m1 = { { "FIRST", 1 }, { "SECOND", 2 } };

    for ( const auto &p : m1 ) 
    {
        std::cout << p.first << '\t' << p.second << std::endl;
    }

    auto to_lower_case = []( const std::pair<const std::string, int> &p )
    {
        std::string t; t.reserve( p.first.size() );
        std::transform( p.first.begin(), p.first.end(),
                        std::back_inserter( t ), ::tolower );
        return std::make_pair( t, p.second );                        
    };

    std::cout << std::endl;

    std::map<std::string, int> m2;

    std::transform( m1.begin(), m1.end(), 
                    std::inserter( m2, m2.begin() ), to_lower_case );

    for ( const auto &p : m2 ) 
    {
        std::cout << p.first << '\t' << p.second << std::endl;
    }
}

程序输出为

FIRST   1
SECOND  2

first   1
second  2

在程序中,使用了std::transform两次。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM