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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12148581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 04:28:43  来源:igfitidea点击:

How to split a sequence into two pieces by predicate?

scala

提问by John Threepwood

How do I split a sequence into two lists by a predicate?

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

Alternative: I can use filterand filterNot, or write my own method, but isn't there a better more general (built-in) method ?

替代方案:我可以使用filterand filterNot,或者编写自己的方法,但是没有更好的更通用(内置)方法吗?

回答by om-nom-nom

By using partitionmethod:

通过使用partition方法:

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

回答by Daniel C. Sobral

Good that partitionwas the thing you wanted -- there's another method that also uses a predicate to split a list in two: span.

很好,这partition正是您想要的——还有另一种方法也使用谓词将列表一分为二:span.

The first one, Boolean):(Repr,Repr)" rel="noreferrer">partitionwill put all "true" elements in one list, and the others in the second list.

第一个,Boolean):(Repr,Repr)" rel="noreferrer">partition会将所有“true”元素放在一个列表中,其他元素放在第二个列表中。

Boolean):(Repr,Repr)" rel="noreferrer">spanwill put all elements in one list until an element is "false" (in terms of the predicate). From that point forward, it will put the elements in the second list.

Boolean):(Repr,Repr)" rel="noreferrer">span会将所有元素放在一个列表中,直到元素为“false”(就谓词而言)。从那时起,它将把元素放在第二个列表中。

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

回答by oxbow_lakes

You might want to take a look at scalex.org- it allows you to search the scala standard library for functions by their signature. For example, type the following:

您可能想看看scalex.org- 它允许您通过签名在 scala 标准库中搜索函数。例如,键入以下内容:

List[A] => (A => Boolean) => (List[A], List[A])

You would see partition.

你会看到partition

回答by nairbv

You can also use foldLeft if you need something a little extra. I just wrote some code like this when partition didn't cut it:

如果您需要一些额外的东西,您也可以使用 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)
    }
  }

回答by Gabber

I know I might be late for the party and there are more specific answers, but you could make good use of groupBy

我知道我可能会迟到,还有更具体的答案,但你可以好好利用 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)

This makes your code a bit more future-proof if you need to change the condition into something non boolean.

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

回答by Matt

If you want to split a list into more than 2 pieces, and ignore the bounds, you could use something like this (modify if you need to search for ints)

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

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"})