在这种情况下可以避免循环吗?

Posted

技术标签:

【中文标题】在这种情况下可以避免循环吗?【英文标题】:Can a loop be avoided in this case? 【发布时间】:2014-11-28 22:26:12 【问题描述】:

我有一个vector<A>,A 有一个字段 A::foo。 我想创建一个向量,其中元素是前一个向量的“foo”。当然我可以遍历向量的元素,但是在 STL 或其他主要库中是否有直接实现?

【问题讨论】:

你的意思是“前一个元素”吗? 不,我的意思是如果 V 是我的原始向量,则新向量 W 的索引 i 处的元素等于 V[i].foo 好的 - 也许你应该包含你的 for 循环版本以明确你想要做什么? 你想要std::transform() 在内部我假设 std::transform 将执行一个循环,但不是吗? 【参考方案1】:

这应该可行

vector<A> vA; // this is your vector<A>, assumed to contain some `A`'s
...
vector<Foo> vFoo; // here is where we extract the Foo's
std::transform(std::begin(vA), std::end(vA), std::back_inserter(vFoo), 
               [](const A& param)return param.foo);

【讨论】:

谢谢大家的回答【参考方案2】:

您可以从&lt;algorithm&gt; 使用std::transform

#include<algorithm>

std::vector<A> as;
// fill it
std::vector<A::foo_type> foos;
foos.resize(as.size());
std::transform(as.begin(), as.end(), foos.begin(), [](const &A)  return A.foo; );

【讨论】:

我想补充一点,resize 将默认构造 foo 的所有元素,这可能会或可能不会导致可观察到的开销。【参考方案3】:

您可以使用 std::transform,但在这种情况下,我认为基于范围的 for 循环更具可读性,并且至少应该与使用 STL 的算法一样高效。


编辑: 为了说明我的观点:

struct Foo ;

struct Bar 
    Foo foo;
;

int main() 
    vector<Bar> bars(10);
    vector<Foo> foos1, foos2, foos3;

    foos1.reserve(bars.size());
    for (const auto& e : bars)  // this will become 'for (e:bars)' in the future
        foos1.push_back(e.foo);
    

    foos2.resize(bars.size());
    transform(bars.begin(), bars.end(), foos2.begin(), [](const Bar& bar)  return bar.foo; );

    foos3.reserve(bars.size());
    transform(bars.begin(), bars.end(), back_inserter(foos3), [](const Bar& bar)return bar.foo; );


在我看来,循环版本更容易阅读(但我承认这可能是个人喜好问题)。

不要误会我的意思,我真的很喜欢算法,但在这种非常简单的情况下,它们的句法开销并没有起到作用。


编辑2: 一些处理器有gather instruction 指令。看看一个典型的编译器是否会生成这些以及在什么条件下会很有趣。

【讨论】:

在效率方面应该没有任何区别 这就是我的假设(当然你必须测量)。根据您编写算法版本的准确程度,编译器绝对可以生成相同的代码,但实际上这并不一定意味着它会。使用算法会增加另一层抽象,编译器在特定情况下可能会或可能无法穿透。然而,编译器总是会为给定的功能生成最有效的代码,而与使用的语法无关,这是一个神话。 一般来说是的。但是,STL(或者更好地称为标准库)的设计考虑到了零开销。因此,就渐近复杂度而言,您在大 O 表示法中肯定具有相同的常数。据我所知,即使是小实例,标准库中的算法也应该非常接近最优。 就大 O 而言,您是完全正确的。然而,在实际硬件上运行时,具有相同复杂度的两种算法(理论上)仍然存在数量级差异。再说一次,我完全同意你的看法,我不希望有什么不同。我只是想说明可能存在差异。

以上是关于在这种情况下可以避免循环吗?的主要内容,如果未能解决你的问题,请参考以下文章

Python pandas:我们可以避免在 groupby/apply 这种情况下应用吗?

我可以避免连接空数据帧的 ValueError 吗?

React - 在不使用 setState 的情况下更改状态:必须避免吗?

我应该避免在现代 C++ 中引用指针还是在这种特殊情况下可以

我可以避免在 EF Core 中使用迁移吗?

我可以通过使用参数来避免所有 SQL 注入攻击吗?