用功能代码代替while循环 [英] Substitute while loop with functional code

查看:93
本文介绍了用功能代码代替while循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在重构一些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时,我需要将值累加到变量vfunction接受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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆