2016-02-15 8 views
10

farklı boyutta aşağıdaki listeleri var varsayalım doldurmak için :Zip İki liste

val desiredResult = ("ax", "by", "c") 

I here teklif edilen

val wrongResult = (list1, list2).zipped map (_ + _) 

çalıştı ancak bu amaçlanan şekilde çalışmaz, zip, eşleştirilemeyen uzun listenin öğelerini atar.

Bu sorunu nasıl çözebilirim? Listeleri sıkıştırmak ve bir liste daha uzunsa "varsayılan öğe" (bu durumda boş dizge gibi) vermek için bir yol var mı?

cevap

26

Aradığınız yöntem .zipAll geçerli:

scala> val list1 = List("a", "b", "c") 
list1: List[String] = List(a, b, c) 

scala> val list2 = List("x", "y") 
list2: List[String] = List(x, y) 

scala> list1.zipAll(list2, "", "") 
res0: List[(String, String)] = List((a,x), (b,y), (c,"")) 

.zipAll 3 argüman alır:

  • varsayılan değer ile fermuarı

    • iterable eğer this (toplama .zipAll çağrılır) daha kısadır
    • diğer koleksiyon ise varsayılan değer kısa
  • +1

    Sanırım her zaman bilmediğimiz bir şey var. –

    +0

    Teşekkürler! Şimdi bu çözüm ile çalışır: 'list1.zipAll (list2," "," ") map ({case (y, x) => y + x})' 'ile daha önce olmadığı gibi' list1.zipAll (list2, ') "," ") harita (_ + _)'. Neden zipAll ile sıkıştırılmış işlev gibi kısa sözdizimini kullanamıyorum? – ForceOfWill

    +1

    @ForceOfWill: '(list1, list2) .zipped' bir' Tuple2Zipped' döndürür, burada ['.map'] (http://www.scala-lang.org/api/current/index.html#scala.runtime .Tuple2Zipped @ map [B, To] (f: (El1, El2) => B) (implicitcbf: scala.collection.generic.CanBuildFrom [Repr1, B, To]): To) bir 'f: (El1 alır El2) => B' (2 argüman alan bir fonksiyon). 'List [A]' '' .map' bir 'f: A => B', yani sadece 1 argüman alır (bu durumda bir' Tuple2''dir). Ne yazık ki bu, '_ + _' (2 argüman alan bir işlevdir) burada uygulanamaz demektir. – Marth

    2

    API tabanlı gitmek yoludur, henüz aşağıdaki gibi yapabilirsiniz (örneğin, bir egzersiz gibi) bunu uygulayabilirsiniz zipAll,

    implicit class OpsSeq[A,B](val xs: Seq[A]) extends AnyVal { 
        def zipAll2(ys: Seq[B], xDefault: A, yDefault: B) = { 
        val xs2 = xs ++ Seq.fill(ys.size-xs.size)(xDefault) 
        val ys2 = ys ++ Seq.fill(xs.size-ys.size)(yDefault) 
        xs2.zip(ys2) 
        } 
    } 
    

    Bu nedenle, örneğin

    Seq(1,2).zipAll2(Seq(3,4,5),10,20) 
    List((1,3), (2,4), (10,5)) 
    

    ve

    list1.zipAll2(list2, "", "") 
    List((a,x), (b,y), (c,"")) 
    
    Varsayılan xd ve varsayılan yd değerleri ile

    bir özyinelemeli sürüm,

    def zipAll3[A,B](xs: Seq[A], ys: Seq[B], xd: A, yd: B): Seq[(A,B)] = { 
        (xs,ys) match { 
        case (Seq(), Seq()) => Seq() 
        case (x +: xss, Seq()) => (x,yd) +: zipAll3(xss, Seq(), xd, yd) 
        case (Seq(), y +: yss) => (xd,y) +: zipAll3(Seq(), yss, xd, yd) 
        case (x +: xss, y +: yss) => (x,y) +: zipAll3(xss, yss, xd, yd) 
        } 
    } 
    

    .