请参阅以下与我的情况相近的伪代码片段:
function foo () {
for ( velocity=0; velocity<100; velocity++ ) {
root1 = computeRoot1();
root2 = computeRoot2();
// do a bunch of computation with root1
// if result of computation is undesirable, do computations again with root2
}
所以,基本上我想在for
循环体内用root1
进行计算,然后root2
如果root1
的计算结果无效。
我的第一直觉是明显的方法,将计算包装在帮助函数中,但我不确定这是最明确的方法。我正在尝试在我的代码中良好地配置信息,并且对代码的函数调用将最多执行两次(每次迭代),但不会为我的代码提供大量简洁性。
我想的可能是for
循环:
for ( root=root1; root1IsInvalid==true || bothRootsInvalid==true; root=root2 )
或具有类似功能的while
。但我当然愿意接受其他建议
当有人阅读此代码时,哪种方法会使其最具可读性和简洁性?
顺便说一句,我正在用JavaScript编写这个特定的函数,但语言无关的解决方案会很棒。
编辑:澄清的代码段
答案 0 :(得分:3)
您有几种基本方法:
for
循环在数组中的每个项上运行相同的代码,可能在满足某些条件时停止迭代。while
循环并重复您的代码,直到满足某些条件。第一个选项更容易扩展到N个项目。对于两个项目,第二个选项可能更简单。
您可以将计算函数设置为本地函数(在您当前正在执行的函数内声明和使用),因此它不会添加到全局命名空间,并且您的代码仍然会被封装更多。
我也不确定你打算用这条线做什么:
root1, root2 = computeRoots();
但是,它只是将值赋给root2
,看起来您可能希望var
在这些值之前将它们定义为局部变量。
答案 1 :(得分:1)
如果热切评估没问题,您可以将您的根收集到一个数组中,并使用roots.filter(isinvalid)
取出无效的数据;然后只使用结果数组中的第一项。
如果你需要延迟评估,可以将它概括为一个函数,该函数在数组上延迟评估函数,直到找到非null结果:
// call fn on items in arr until fn returns non-null
// returns [item, result]
// if result===false, no true value was returned
function firstNotNull(fn, arr) {
var i, length, item, result=null;
for (i = 0, length=arr.length; i < length; i++) {
item = arr[i];
result = fn(item);
if (result!==null) {
break;
}
}
return [item, result];
}
function rootComputations(root) {
var computationResult = null;
if (root==1) {
computationResult = 1;
}
return computationResult;
}
function computeRoots() {
return [0,1];
}
function foo() {
var velocity, roots, root, result, computations;
for (velocity = 0; velocity < 100; velocity++) {
roots = computeRoots();
computations = firstNotNull(rootComputations, roots);
console.log(computations);
root = computations[0];
result = computations[1];
}
}
foo();
您可以进一步概括firstNotNull()
:
// call fn on items in arr until cond(fn(item)) returns true
// returns [item, fn(item)], or null if unsatisfied
function firstSatisfying(cond, fn, arr) {
var i, length, item, fnitem, result=null;
for (i = 0, length=arr.length; i < length; i++) {
item = arr[i];
fnitem = fn(item);
if (cond(fnitem)) {
result = [item, fnitem];
break;
}
}
return result;
}
var firstNotNull = firstSatisfying.bind(null, function(item){return item!==null;});
您现在拥有一个通用函数,用于获取满足您所需条件的第一个列表。
ECMAScript 5添加了许多方法,这些方法使得渴望功能应用程序更容易在数组上运行,但Javascript没有任何用于 lazy 评估的本机工具。如果这是您认为经常需要的东西,请考虑使用stream.js,它提供“流”数据类型以及部分应用的方法。使用stream.js,您的逻辑将如下所示:
// rootStream should be a function which returns a Stream
// It should construct a stream with the first root produced
// and a function that returns the remaining roots.
// Since I don't know how you get your roots, I'll use a stupid example:
function rootStream() {
return new Stream(0, function(){
return new Stream(1);
});
}
function isvalid(root) {
return root===1;
}
Stream.range(0,100)
.walk(function(v){
//v doesn't seem to be used?
var firstvalid = rootStream().filter(isvalid).head();
console.log(firstvalid);
});