Bir dizi yüklemeye göre nasıl iki parçaya bölünür?


120

Bir diziyi bir yüklemeye göre iki listeye nasıl bölerim?

Alternatif: Kullanabilir filterve filterNotveya kendi yöntemimi yazabilirim, ancak daha genel (yerleşik) bir yöntem yok mu?

Yanıtlar:


194

partitionYöntemi kullanarak :

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)sonuçtaki demeti partitionokunabilir bir şekilde yok etmenin bir yoludur.
— k0pernikus

2
Bir bölüm içindeki işlevi kısaltabilir _ % 2 == 0.
— k0pernikus

138

İyi partitionİstediğin şeydi - ayrıca ikiye listesini bölmek için bir yüklemi kullanan başka bir yöntem var: span.

İlki, bölüm tüm "true" öğeleri bir listeye ve diğerlerini ikinci listeye koyacaktır.

span , bir öğe "yanlış" olana kadar (yüklem açısından) tüm öğeleri tek bir listeye koyacaktır. Bu noktadan sonra, öğeleri ikinci listeye koyacaktır.

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

2
Tam olarak aradığım şey. Liste ilgili bir kritere göre sıralandığında bu çok daha mantıklıdır.
— erich2k8

16

Scalex.org'a bir göz atmak isteyebilirsiniz - bu, scala standart kitaplığında işlevleri imzalarına göre aramanıza olanak tanır. Örneğin, şunu yazın:

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

Bölme göreceksiniz .


10
scalex.org alanı şu anda kapanmış. Ama alternatif var - scala-search.org ;-).
— monnef

1
Balık tutmayı öğretmek!
— BU KULLANICININ YARDIM İHTİYACI

1
@monnef 2020 alternatifiniz için bir alternatif var mı? :)
— tehCivilian

14

Biraz fazladan bir şeye ihtiyacınız varsa foldLeft'i de kullanabilirsiniz. Bölüm kesmediğinde böyle bir kod yazdım:

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
Tuple ve foldLeft kullanmanın çok güzel yolu İki listeyi aynı sırada verimli bir şekilde tutmak için bir ListBuffer kullanmaya son verdim, ancak aksi halde ihtiyacım olan şey için yerinde idi.
— Matt Hagopian

1

Partiye geç kalabileceğimi ve daha spesifik cevaplar olduğunu biliyorum, ancak şunu iyi bir şekilde kullanabilirsiniz: 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)

Bu, koşulu boole olmayan bir şeye dönüştürmeniz gerekiyorsa kodunuzu biraz daha geleceğe hazır hale getirir.


0

Bir listeyi 2'den fazla parçaya bölmek ve sınırları göz ardı etmek istiyorsanız, bunun gibi bir şey kullanabilirsiniz (ints'i aramanız gerekiyorsa değiştirin)

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"})
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.