你如何遍历scala中的每个状态?

How do you iterate through each status in scala?

我正在尝试遍历每个状态以检查 ArrayList 是否至少有 1 个 ACTIVE 和 1 个 INACTIVE 状态。

var active = false;
var inactive = false;
for (item <- reasons.items) {
  if(item.status == "ACTIVE")
    active = true
  if(item.status == "INACTIVE")
    }
active must be (true)
inactive must be (true)

有没有更简洁的方法来做到这一点?我尝试过这样的流,但没有成功

var active = false;      
var stream = reasons.items.toStream
        .forEach(item => if(item.status == "ACTIVE") {active = true})

注:原因保留项(有 1 项)。 items 包含可以像 reasons.items.get(x).

这样调用的单个项目

干净的方法是

val active = reasons.items.exists(item => item.status == "ACTIVE")

或更短

val active = reasons.items.exists(_.status == "ACTIVE")

val inactive 类似。这确实存在遍历列表两次的问题(但与您的代码不同,两次都找到合适的项目后停止)。

对于 "at least 1",您可以在 items 上使用 exists 来检查给定的谓词,如果至少有一项满足条件,则 returns 为真。对于 "ACTIVE and INACTIVE",您可以组合两个 exists 调用,使用 && 的低效方法。

reasons.items.exists(_.status.equals("ACTIVE")) && reasons.items.exists(_.status.equals("INACTIVE"))`

其他答案很好地解释了如何使用 Scala 集合来实现这一点。由于看起来您正在使用 ScalaTest,因此我想补充一点,您也可以使用 ScalaTest 来遍历元素。

使用检查员的循环式语法:

forAtLeast(1, reasons.items) { item =>
  item.status must be ("ACTIVE")
}

forAtLeast(1, reasons.items) { item =>
  item.status must be ("INACTIVE")
}

请注意,检查器与匹配器是分开定义的,因此您必须 import org.scalatest.Inspectors._extends … with org.scalatest.Inspectors 才能将 forAtLeast 纳入范围。

如果你想避免来自检查器的循环式语法,你可以使用检查器 shorthand 语法和基于反射的 have 语法:

atLeast(1, reasons.items) must have ('status "ACTIVE")
atLeast(1, reasons.items) must have ('status "INACTIVE")

如果您想避免 have 的基于反射的语法,您可以扩展 have 语法以直接支持您的 status 属性:

def status(expectedValue: String) =
  new HavePropertyMatcher[Item, String] {
    def apply(item: Item) =
      HavePropertyMatchResult(
        item.status == expectedValue,
        "status",
        expectedValue,
        item.title
      )
  }

atLeast(1, reasons.items) must have (status "ACTIVE")
atLeast(1, reasons.items) must have (status "INACTIVE")

或者如果您更喜欢 be 而不是 have,您可以扩展 be 语法以添加对 activeinactive 的支持:

class StatusMatcher(expectedValue: String) extends BeMatcher[Item] {
  def apply(left: Item) =
    MatchResult(
      left.status == expectedValue,
      left.toString + " did not have status " + expectedValue,
      left.toString + " had status " + expectedValue,
    )
}

val active = new StatusMatcher("ACTIVE")
val inactive = new statusMatcher("INACTIVE")

atLeast(1, reasons.items) must be (active)
atLeast(1, reasons.items) must be (inactive)

在这里的示例中,定义自己的匹配器只是为了在断言中节省几个单词看起来有点傻,但是如果您针对相同的属性编写数百个测试,那么获取您的匹配器会非常方便断言减少到一行,并且仍然自然可读。所以根据我的经验,如果你在很多测试中重用它们,像这样定义你自己的匹配器是有意义的。