用功能代码代替while循环 [英] Substitute while loop with functional code
问题描述
我正在重构一些Scala代码,而while循环遇到了问题.旧代码是:
I am refactoring some scala code and I am having problems with a while loop. The old code was:
for (s <- sentences){
// ...
while (/*Some condition*/){
// ...
function(trees, ...)
}
}
我已经使用foldLeft
横切了sentences
将该代码翻译成这一代码:
I've have translated that code into this one, using foldLeft
to transverse sentences
:
sentences./:(initialSeed){
(seed, s) =>
// ...
// Here I've replaced the while with other foldleft
trees./:(seed){
(v, n) =>
// ....
val updatedVariable = function(...., v)
}
}
现在,可能是我需要停止横向移动trees
的原因(内部foldLeft
完全横切之前,因为我已经找到了这个问题:
Now, It may be the case that I need to stop transversing trees
(The inner foldLeft
before it is transverse entirely, for that I've found this question:
但是我也有以下问题:
当我横穿trees
时,我需要将值累加到变量v
,function
接受v
并返回更新的v
,在此称为updatedVariable
.问题是我感觉这不是编码此功能的正确方法.
As I transverse trees
, I need to accumulate values to the variable v
, function
takes v
and returns an updated v
, called here updatedVariable
. The problem is that I have the feeling that this is not a proper way of coding this functionality.
您能建议我这样做的一种功能/不变的方法吗?
Could you recommended me a functional/immutable way of doing this?
注意::我已经简化了代码以显示实际问题,完整的代码是这样:
NOTE: I've simplified the code to show the actual problem, the complete code is this:
val trainVocabulart = sentences./:(Vocabulary()){
(vocab, s) =>
var trees = s.tree
var i = 0
var noConstruction = false
trees./:(vocab){
(v, n) =>
if (i == trees.size - 1) {
if (noConstruction) return v
noConstruction = true
i = 0
} else {
// Build vocabulary
val updatedVocab = buildVocabulary(trees, v, i, Config.LeftCtx, Config.RightCtx)
val y = estimateTrainAction(trees, i)
val (newI, newTrees) = takeAction(trees, i, y)
i = newI
trees = newTrees
// Execute the action and modify the trees
if (y != Shift)
noConstruction = false
Vocabulary(v.positionVocab ++ updatedVocab.positionVocab,
v.positionTag ++ updatedVocab.positionTag,
v.chLVocab ++ updatedVocab.chLVocab,
v.chLTag ++ updatedVocab.chLTag,
v.chRVocab ++ updatedVocab.chRVocab,
v.chRTag ++ updatedVocab.chRTag)
}
v
}
}
还有旧的:
for (s <- sentences) {
var trees = s.tree
var i = 0
var noConstruction = false
var exit = false
while (trees.nonEmpty && !exit) {
if (i == trees.size - 1) {
if (noConstruction) exit = true
noConstruction = true
i = 0
} else {
// Build vocabulary
buildVocabulary(trees, i, LeftCtx, RightCtx)
val y = estimateTrainAction(trees, i)
val (newI, newTrees) = takeAction(trees, i, y)
i = newI
trees = newTrees
// Execute the action and modify the trees
if (y != Shift)
noConstruction = false
}
}
}
推荐答案
第一-您很难做到这一点.您的简化示例或完整示例都不够完整,无法编译.
1st - You don't make this easy. Neither your simplified or complete examples are complete enough to compile.
2nd-您提供了一些链接,可以链接到早期爆发问题的一些合理解决方案.有没有理由使它们都不适合您的情况?
2nd - You include a link to some reasonable solutions to the break-out-early problem. Is there a reason why none of them look workable for your situation?
3rd-完整的示例是否真的有效?您正在折叠一个变体...
3rd - Does that complete example actually work? You're folding over a var ...
trees./:(vocab){
...在该操作中,您可以修改/更新该变量...
... and inside that operation you modify/update that var ...
trees = newTrees
根据我的测试,这是毫无意义的陈述.通过更新集合,原始迭代不会改变.
According to my tests that's a meaningless statement. The original iteration is unchanged by updating the collection.
4th-我不相信fold
是您想要的. fold
遍历一个集合并将其减小为单个值,但是您的目标似乎并不是要找到该单个值. /:
的结果将被丢弃.没有val result = trees./:(vocab){...
4th - I'm not convinced that fold
is what you want here. fold
iterates over a collection and reduces it to a single value, but your aim here doesn't appear to be finding that single value. The result of your /:
is thrown away. There is no val result = trees./:(vocab){...
您可能会看到的一个解决方案是:trees.forall{ ...
在每次迭代结束时,如果应该继续进行下一次迭代,则只需返回true
.
One solution you might look at is: trees.forall{ ...
At the end of each iteration you just return true
if the next iteration should proceed.
这篇关于用功能代码代替while循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!