Scala'da ikiden fazla listeyi birlikte sıkıştırabilir miyim?


94

Aşağıdaki Scala Listesi verildiğinde:

val l = List(List("a1", "b1", "c1"), List("a2", "b2", "c2"), List("a3", "b3", "c3"))

Nasıl alabilirim:

List(("a1", "a2", "a3"), ("b1", "b2", "b3"), ("c1", "c2", "c3"))

Zip yalnızca iki Listeyi birleştirmek için kullanılabildiğinden, ana Listeyi bir şekilde yinelemeniz / azaltmanız gerektiğini düşünüyorum. Şaşırtıcı olmayan bir şekilde, aşağıdakiler çalışmıyor:

scala> l reduceLeft ((a, b) => a zip b)
<console>:6: error: type mismatch;
 found   : List[(String, String)]
 required: List[String]
       l reduceLeft ((a, b) => a zip b)

Bunun nasıl yapılacağına dair herhangi bir öneriniz var mı? Sanırım bunu yapmanın çok basit bir yolunu kaçırıyorum.

Güncelleme: Her biri M öğeli N Listeleri Listesi alabilen ve M TupleNs Listesi oluşturabilen bir çözüm arıyorum.

Güncelleme 2: Görünüşe göre, benim özel kullanım durumumda bir grup listesi yerine bir liste listesine sahip olmak daha iyi, bu yüzden balkabağının yanıtını kabul ediyorum. Yerel bir yöntem kullandığı için aynı zamanda en basit olanıdır.



Kesinlikle
kayda

@VenkatSudheerReddyAedama Ayrıca beş gün sonra benim tarafımdan da soruldu. ;-)
pr1001

Yanıtlar:


36

Rastgele boyutta bir demet listesi oluşturmanın mümkün olduğuna inanmıyorum, ancak bunun yerine bir liste listesi almaktan çekinmiyorsanız, devrik işlevi tam olarak ihtiyacınız olanı yapar.


Teşekkürler, bu mükemmel çalışıyor! Özel kullanım durumuma girerken, çeşitli alt listeleri eşleştirmem ve azaltmam gerektiğinden, bir liste listesinin yine de daha iyi olacağını görüyorum.
pr1001

2
@JoshCason "ikiden fazla" nın en dar anlamıyla, tabii. Üç gerçekten ikiden fazladır. Soruyu daha geniş anlamda "ikiden fazla" olarak yorumladım, yani keyfi olarak çok fazla. Ve bu durumda, sorulara HListve benzerlerine ulaşmadığınız sürece, sorunun istediğini yapmak mümkün değildir .
copumpkin


216
scala> (List(1,2,3),List(4,5,6),List(7,8,9)).zipped.toList
res0: List[(Int, Int, Int)] = List((1,4,7), (2,5,8), (3,6,9))

Gelecekte referans olması için.


32
Bu, üç listeyi sıkıştırmak için harika. Yazık ki bu üç listeden fazla işe yaramıyor :(
2014

2
Bunun önce bir demet içinde olması gerektiğini unutmayın: zippedbir işlevi değil List.
Nathaniel Ford

7
zippedScala 2.13'te kullanımdan kaldırılmıştır. l1.lazyZip(l2).lazyZip(l3).toList
2.13'te

30

Yani bu kod parçası OP'nin ihtiyaçlarına cevap vermeyecek ve sadece bu dört yıllık bir konu olduğu için değil, aynı zamanda başlık sorusuna cevap veriyor ve belki birileri onu faydalı bulabilir.

3 koleksiyonu sıkıştırmak için:

as zip bs zip cs map { 
  case ((a,b), c) => (a,b,c)
}

4 koleksiyon yapmak şuna benzer:as zip bs zip cs zip ds map { case ((a,b),c)} map {case ((a,b),c,d)=>(a,b,c,d)}
James Tobin

1
@JamesTobin, u kısaltınas zip bs zip cs zip ds map {case (((a,b),c),d)=>(a,b,c,d) }
keepcoding

Farklı türdeki listeler için güzel.
FP Serbestçe

11

Evet, zip3 ile .


2
Teşekkürler, ancak yalnızca 3 listeyle çalışır. Her biri M öğeli N Listeleri Listesi alıp M TupleNs Listesi oluşturabilen bir çözüm arıyorum.
pr1001

6

transposehile yapar. Olası bir algoritma:

def combineLists[A](ss:List[A]*) = {
    val sa = ss.reverse;
    (sa.head.map(List(_)) /: sa.tail)(_.zip(_).map(p=>p._2 :: p._1))
}

Örneğin:

combineLists(List(1, 2, 3), List(10,20), List(100, 200, 300))
// => List[List[Int]] = List(List(1, 10, 100), List(2, 20, 200))

Cevap, girişteki en kısa listenin boyutuna kısaltılır.

combineLists(List(1, 2, 3), List(10,20))
// => List[List[Int]] = List(List(1, 10), List(2, 20))

1
bu cevap neredeyse hile yapar, ancak unsurları tersine çevirir. Çıktıyı beklenen sırada üreten gelişmiş bir sürüm önerebilir misiniz? teşekkürler
fracca

Şu sıralamayı tutan değiştirilmiş sürüm: def combineLists[A](ss:List[A]*) = { val sa = ss.reverse; (sa.head.map(List(_)) /: sa.tail)(_.zip(_).map(p=>p._2 :: p._1)) }
rogermenezes

5

Tüm farklı sınıflar olarak farklı tanımlama grubu boyutlarda Scala davranır ( Tuple1, Tuple2, Tuple3, Tuple4, ..., Tuple22onlar tüm devralma yaparken) Product, özelliğin aslında dizilerini farklı boyutlarda veri değerlerini kullanmak özellik yeterli bilgi taşımaması koşuluyla hepsi aynı işlev tarafından döndürülebilirse. (Ve scala'nın jenerikleri de bu davayı ele alacak kadar güçlü değil.)

En iyi bahsiniz, 22 Tuple boyutunun tümü için zip işlevinin aşırı yüklemelerini yazmaktır. Bir kod üreteci muhtemelen bu konuda size yardımcı olacaktır.


5

Uygulanabilir scalaz / cats / (en sevdiğiniz işlevsel kütüphaneyi buraya ekleyin) rotasından aşağı inmek istemiyorsanız, örüntü eşleştirme gidilecek yoldur, ancak (_, _)sözdizimi iç içe geçme konusunda biraz garip olsa da , hadi değiştirelim:

import scala.{Tuple2 => &}

for (i1 & i2 & i3 & i4 <- list1 zip list2 zip list3 zip list4) yield (i1, i2, i3, i4)

&Burada keyfi bir seçim yapmalı güzel infix görünüyor herşeydir. Yine de, kod incelemesi sırasında muhtemelen birkaç kaşınız kalkacaktır.

Ayrıca yapabileceğiniz herhangi bir şeyle de çalışmalıdır zip(ör. FutureS)


5

Tekrar etmeden bunun mümkün olduğuna inanmıyorum. Basit bir nedenden ötürü: istediğiniz işlevin geri dönen türünü tanımlayamazsınız.

Örneğin, girdiniz olsaydı List(List(1,2), List(3,4)), dönüş türü olurdu List[Tuple2[Int]]. Üç elemanı olsaydı, dönüş türü olurduList[Tuple3[Int]] , vb.

Geri dönebilir List[AnyRef], hatta List[Product]ve sonra her koşul için bir tane olmak üzere bir dizi vaka oluşturabilirsiniz.

Genel Liste aktarımına gelince, bu çalışır:

def transpose[T](l: List[List[T]]): List[List[T]] = l match {
  case Nil => Nil
  case Nil :: _ => Nil
  case _ => (l map (_.head)) :: transpose(l map (_.tail))
}

Bu, rastgele boyutlandırılmış listeler için işe yaramaz. Örneğin: transpose (List (List ("a", "b"), List ("c")))
Sudheer Aedama

1
@VenkatSudheerReddyAedama Eksik matrislerin aktarılması bana mantıklı gelmiyor. Örneğin, eğerc doğrultusunda aveya b? Ve diğeriyle aynı çizgide olduğunu nasıl temsil edersiniz?
Daniel C. Sobral

Kabul. Bu tamamlanmamış bir matris. ZipAll çizgisinde bir şey arıyordum. Benim durumumda, uyumlu colduğunu söyleyin a(yani, indeksle uyumlu)?
Sudheer Aedama

2

ürün koleksiyonlarıflatZip 22'ye kadar bir işleyişe sahiptir .

scala> List(1,2,3) flatZip Seq("a","b","c") flatZip Vector(1.0,2.0,3.0) flatZip Seq(9,8,7)
res1: com.github.marklister.collections.immutable.CollSeq4[Int,String,Double,Int] = 
CollSeq((1,a,1.0,9),
        (2,b,2.0,8),
        (3,c,3.0,7))

0

Scalaz ile:

import scalaz.Zip
import scalaz.std.list._

// Zip 3
Zip[List].ap.tuple3(List("a1", "b1"),
                    List("a2", "b2"),
                    List("a3", "b3"))

// Zip 4
Zip[List].ap.tuple4(List("a1", "b1"),
                    List("a2", "b2"),
                    List("a3", "b3"),
                    List("a4", "b4"))

// Zip 5
Zip[List].ap.tuple5(List("a1", "b1"),
                    List("a2", "b2"),
                    List("a3", "b3"),
                    List("a4", "b4"),
                    List("a5", "b5"))

5'ten fazlası için:

// Zip 6
Zip[List].ap.apply6(List("a1", "b1"),
                    List("a2", "b2"),
                    List("a3", "b3"),
                    List("a4", "b4"),
                    List("a5", "b5"),
                    List("a6", "b6"))((_, _, _, _, _, _))

// Zip 7
Zip[List].ap.apply7(List("a1", "b1"),
                    List("a2", "b2"),
                    List("a3", "b3"),
                    List("a4", "b4"),
                    List("a5", "b5"),
                    List("a6", "b6"),
                    List("a7", "b7"))((_, _, _, _, _, _, _))

...

// Zip 12
Zip[List].ap.apply12(List("a1", "b1"),
                     List("a2", "b2"),
                     List("a3", "b3"),
                     List("a4", "b4"),
                     List("a5", "b5"),
                     List("a6", "b6"),
                     List("a7", "b7"),
                     List("a8", "b8"),
                     List("a9", "b9"),
                     List("a10", "b10"),
                     List("a11", "b11"),
                     List("a12", "b12"))((_, _, _, _, _, _, _, _, _, _, _, _))
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.