STL的算法可组合

问题描述 投票:36回答:4

STL算法是在C ++中一个非常有用的东西。但有一件事那种认为我厌烦的是,他们似乎缺乏可组合。

举例来说,假设我有一个vector<pair<int, int>>并希望变换到只包含对的vector<int>部件second。这是很简单的:

std::vector<std::pair<int, int>> values = GetValues();
std::vector<int> result;

std::transform(values.begin(), values.end(), std::back_inserter(result),
    [] (std::pair<int, int> p) { return p.second; });

或者,也许我要筛选只有那些对他们vector成员是连first。也很简单:

std::vector<std::pair<int, int>> values = GetValues();
std::vector<std::pair<int, int>> result;

std::copy_if(values.begin(), values.end(), std::back_inserter(result),
    [] (std::pair<int, int> p) { return (p.first % 2) == 0; });

但是,如果我想做什么都?没有transform_if算法,并同时使用transformcopy_if似乎需要分配一个临时的vector来保存中间结果:

std::vector<std::pair<int, int>> values = GetValues();
std::vector<std::pair<int, int>> temp;
std::vector<int> result;

std::copy_if(values.begin(), values.end(), std::back_inserter(temp),
    [] (std::pair<int, int> p) { return (p.first % 2) == 0; });

std::transform(values.begin(), values.end(), std::back_inserter(result),
    [] (std::pair<int, int> p) { return p.second; });

这似乎有点浪费了我。我能想到的,以避免临时vector的唯一办法是放弃transformcopy_if和简单地使用for_each(或定期for循环,哪个适合你的想象):

std::vector<std::pair<int, int>> values = GetValues();
std::vector<int> result;

std::for_each(values.begin(), values.end(),
    [&result] (std::pair<int, int> p) 
        { if( (p.first % 2) == 0 ) result.push_back(p.second); });

我失去了一些东西在这里?有组成两个现有的STL算法集成到一个新的,而不需要临时存储的好办法?

c++ stl stl-algorithm
4个回答
24
投票

你是对的。您可以使用Boost.Range adaptors实现组成。


11
投票

我认为这个问题是很遗憾的结构

  1. C ++使用两个迭代来表示一个序列
  2. C ++函数是单值

所以你不能把它们连,因为函数无法返回“序列”。

一种选择会是使用单对象序列代替(like the range approach from boost)。这样,您可能已经合并一个加工为一体的另一个输入的结果......(一个对象 - >一个对象)。

在标准C ++库,而不是处理(两个对象 - >一个物体)和很显然,这不能没有命名临时对象被链接。


8
投票

早在2000年,这个问题已经提到。加里·鲍威尔和马丁·韦泽想出了一个“看”理念,并创造了名为“查看模板库”。它没有起飞,那么但这个想法是有道理的。 “查看”适配器基本上是适用的上即时变换。例如,它可以适应value_type

这个概念可能要重新寻址现在我们的C ++ 0x。自2000年以来,我们已经取得了在泛型编程相当一些进展。

例如,让我们使用vector<pair<int, int>>vector<int>例子。这可能是很简单的:

std::vector<std::pair<int, int>> values = GetValues();
vtl2::view v (values, [](std::pair<int, int> p) { return p.first }); 
std::vector<int> result(view.begin(), view.end());

或者,使用boost::bind技术,更简单:

std::vector<std::pair<int, int>> values = GetValues();
vtl2::view v (values, &std::pair<int, int>::first); 
std::vector<int> result(view.begin(), view.end());

0
投票

不知道这是仍然活跃,但...另眼相看等待头只LIB,做你的描述。关于懒惰的评价和COM蒹容生成文件的谈判。

文档片段:

  • 读入,直到从文件“的test.txt” 10点的整数。
  • 筛选偶数,方他们并总结他们的价值观。
    int total = lz::read<int>(ifstream("test.txt")) | lz::limit(10) |
                lz::filter([](int i) { return i % 2 == 0; }) |
                lz::map([](int i) { return i *  i; }) | lz::sum();

您可以拆分该行成多个表达式。

    auto numbers = lz::read<int>(ifstream("test.txt")) | lz::limit(10);
    auto evenFilter = numbers | lz::filter([](int i) { return i % 2 == 0; });
    auto squares = evenFilter | lz::map([](int i) { return i *  i; });
    int total = squares | lz::sum();
  • 尽管这种表达被分割在多个变量赋值,它不是任何效率较低。
  • 每个中间变量简单地描述要执行的代码单元。在堆栈中的所有举行。

https://github.com/SaadAttieh/lazyCode

© www.soinside.com 2019 - 2024. All rights reserved.