述語によってシーケンスを2つの部分に分割する方法は?


120

シーケンスを述語によって2つのリストに分割するにはどうすればよいですか?

代替:filterand を使用しfilterNotたり、独自のメソッドを記述したりできますが、より一般的な(組み込み)メソッドはありませんか?

回答:


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。リストを2つに分割するために述語も使用する別の方法があります。

最初のパーティションは、すべての「真の」要素を1つのリストに入れ、その他は2番目のリストに入れます。

spanは、要素が(述語に関して) "false"になるまで、すべての要素を1つのリストに配置します。その時点以降、2番目のリストに要素が配置されます。

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

2
まさに私が探していたもの。リストが関連する基準で順序付けられている場合、これは非常に理にかなっています。
erich2k8 2013

16

あなたはscalex.orgを見てみたいかもしれません-それはあなたがそれらのシグネチャによって関数のためにスカラ標準ライブラリを検索することを可能にします。たとえば、次のように入力します。

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

パーティションが表示さます。


10
scalex.orgドメインは現在停止しています。しかし、代替案があります-scala-search.org ;-)。
monnef 2016

1
魚の捕り方を教える!
このユーザーにはヘルプが必要です

1
@monnef 2020年の代替案の代替案はありますか?:)
tehCivilian

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を使用して2つのリストを効率的に同じ順序に保つことになりましたが、それ以外は必要なものにスポットを当てていました。
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

リストを3つ以上に分割し、境界を無視する場合は、次のようなものを使用できます(intを検索する必要がある場合は変更します)

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"})
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.