我有一个 Vec3 类。 替换循环的最佳方法是什么
for (int x = 20; x < 25; x++)
for (int y = 40; y < 45; y++)
for (int z = 2; z < 4; z++) doStuff({x,y,z});
像这样:
for(Vec3 v: Vec3range({20,40,2}, {25,45,4}))
doStuff(v);
没有任何运行成本?
最佳答案
为此,我在 functional library fn 中编写了一个迭代 和一个组合 适配器:
#include <fn.h>
#include <iostream>
int main() {
using std; using fn;
for (auto &&values : combine(seq(20,25), seq(40,45), seq(2,4))) {
int x, y, z;
tie(x, y, z) = values;
cout << x << ", " << y << ", " << z << "\n";
// or in your case: doStuff({x, y, z});
}
}
输出:
20, 40, 2
20, 40, 3
20, 41, 2
20, 41, 3
...
24, 43, 2
24, 43, 3
24, 44, 2
24, 44, 3
此处,seq(a, b) 返回一个隐式范围,该范围遍历值 [a, b)(即第一个是包含的,第二个是独占的)。 (第三个参数可以指定步骤,并且存在更复杂的替代方案以更好地控制迭代。)
combine(ranges...) 函数返回一个隐式范围,该范围迭代所有组合给定范围(其中第一个被认为是“最重要的”一个,类似于您的“最外层”循环)。它的迭代器取消对保存当前组合的 std::tuple 的引用。
然后这个元组在循环体中绑定(bind)到一些变量。 (遗憾的是,没有像 for(tie(auto x, auto y, auto z) : ...) 这样的基于范围的 for 循环的“自动绑定(bind)”。)
seq() 这很简单:它是一个返回适配器对象的函数,该对象具有 begin() 和 end() 函数。它们返回一个自定义迭代器,该迭代器在 operator++ 中递增当前值并在 operator* 中返回它。
combine() 这更有趣:它返回一个适配器对象,该对象保存作为元组成员中的 combine 参数提供的范围。此适配器的迭代器将迭代器保存到元组成员中的包装范围,但是三次:当前位置、开始和结束,您很快就会明白为什么。
迭代器的 operator++ 很可能是最有趣的一个:它是使用 variadic_ops.h, va_next_combination() 中的可变参数模板递归实现的。它被赋予三元组的迭代器(对于每个范围,当前、开始和结束):
// base case
inline bool va_next_combination() {
return true;
}
// recursive case
template<typename Head, typename ...Tail>
inline bool va_next_combination(std::tuple<Head&,Head&,Head&> && curr_and_begin_and_end, std::tuple<Tail&,Tail&,Tail&> &&...t) {
// advance the "tail" to its next combination and check if it had an overflow
if (va_next_combination(std::forward<std::tuple<Tail&,Tail&,Tail&>>(t)...)) {
// advance the "head" iterator
++std::get<0>(curr_and_begin_and_end);
// check if the "head" just overflow
bool at_end = (std::get<0>(curr_and_begin_and_end) == std::get<2>(curr_and_begin_and_end));
// if it did, put it back to the beginning and report the overflow
if (at_end) std::get<0>(curr_and_begin_and_end) = std::get<1>(curr_and_begin_and_end);
return at_end;
} else {
// "tail" didn't overflow, so we do nothing and no overflow should be reported
return false;
}
}
从集合中最右边的迭代器开始,它递增迭代器。如果它刚刚到达范围的末尾,它会将其报告为递归函数的返回值。下一个迭代器检查该值,如果它是真的,它自己需要前进(否则不需要)以及“重置”右边的迭代器(即“环绕”它的溢出),最后它向在左边。
如果您从最深递归级别的“if”条件开始,这就是机械计数器的基本工作方式。
关于c++ - 用基于范围的 for 循环替换多维 for 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26514527/
我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
似乎无法为此找到有效的答案。我正在阅读Rails教程的第10章第10.1.2节,但似乎无法使邮件程序预览正常工作。我发现处理错误的所有答案都与教程的不同部分相关,我假设我犯的错误正盯着我的脸。我已经完成并将教程中的代码复制/粘贴到相关文件中,但到目前为止,我还看不出我输入的内容与教程中的内容有什么区别。到目前为止,建议是在函数定义中添加或删除参数user,但这并没有解决问题。触发错误的url是http://localhost:3000/rails/mailers/user_mailer/account_activation.http://localhost:3000/rails/mai
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que