如何通过谓词将序列分为两部分?


120

如何通过谓词将序列分成两个列表?

备选:我可以使用filterfilterNot,也可以编写自己的方法,但是没有更好的通用(内置)方法吗?

Answers:


193

通过使用partition方法:

scala> List(1,2,3,4).partition(x => x % 2 == 0)
res0: (List[Int], List[Int]) = (List(2, 4),List(1, 3))

1
val (even, odd) = List(1,2,3,4).partition(x => x % 2 == 0)是一种以partition可读方式破坏结果元组的方法。
k0pernikus

2
可以将分区内的功能缩短为_ % 2 == 0
k0pernikus

138

好了,partition这就是您想要的东西-另一种方法也使用谓词将列表分成两部分:span

第一个分区将所有“ true”元素放在一个列表中,其他元素则放在第二个列表中。

span将所有元素放在一个列表中,直到一个元素为“ false”(根据谓词)。从那时起,它将把元素放在第二个列表中。

scala> Seq(1,2,3,4).span(x => x % 2 == 0)
res0: (Seq[Int], Seq[Int]) = (List(),List(1, 2, 3, 4))

2
正是我想要的。当按照相关标准对列表进行排序时,这更有意义。
erich2k8


14

如果您需要一些额外的东西,也可以使用foldLeft。当分区没有剪切时,我只是写了一些这样的代码:

val list:List[Person] = /* get your list */
val (students,teachers) = 
  list.foldLeft(List.empty[Student],List.empty[Teacher]) {
    case ((acc1, acc2), p) => p match {
      case s:Student => (s :: acc1, acc2)
      case t:Teacher  => (acc1, t :: acc2)
    }
  }

1
使用元组和foldLeft的非常好方法。我最终使用了ListBuffer来有效地使两个列表保持相同的顺序,但否则就满足了我的需要。
Matt Hagopian 2014年

1

我知道我参加聚会可能会迟到,还有更多具体答案,但是您可以充分利用 groupBy

val ret = List(1,2,3,4).groupBy(x => x % 2 == 0)

ret: scala.collection.immutable.Map[Boolean,List[Int]] = Map(false -> List(1, 3), true -> List(2, 4))

ret(true)
res3: List[Int] = List(2, 4)

ret(false)
res4: List[Int] = List(1, 3)

如果您需要将条件更改为非布尔值,这将使您的代码更具前瞻性。


0

如果要将列表分成两个以上的部分,并忽略边界,则可以使用类似的方法(如果需要搜索整数,则可以进行修改)

def split(list_in: List[String], search: String): List[List[String]] = {
  def split_helper(accum: List[List[String]], list_in2: List[String], search: String): List[List[String]] = {
    val (h1, h2) = list_in2.span({x: String => x!= search})
    val new_accum = accum :+ h1
    if (h2.contains(search)) {
      return split_helper(new_accum, h2.drop(1), search) 
    }
    else {
    return accum
    }
  }
  return split_helper(List(), list_in, search)
}

// TEST

// split(List("a", "b", "c", "d", "c", "a"), {x: String => x != "x"})
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.