Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zip two lists of different lengths with default element to fill

Assume we have the following lists of different size:

val list1 = ("a", "b", "c")
val list2 = ("x", "y")

Now I want to merge these 2 lists and create a new list with the string elements being concatenated:

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

I tried

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

as proposed here, but this doesn't work as intended, because zip discards those elements of the longer list that can't be matched.

How can I solve this problem? Is there a way to zip the lists and give a "default element" (like the empty string in this case) if one list is longer?

like image 431
ForceOfWill Avatar asked Feb 15 '16 09:02

ForceOfWill


People also ask

Can you zip two lists?

You can also zip two lists in python with the combination of zip() function and for loop. It is the least used method where the interlist aggregation can be done with the chain function, while the intralist aggregation can be done with the zip() function.

Can I use zip for more than two lists Python?

In Python, the built-in function zip() aggregates multiple iterable objects (lists, tuples, etc.). You can iterate multiple lists in the for loop with zip() .

How many items are in a 5 item ZIP file?

This means, that if you pass in a list that is 5 items long, and another list that is one million items long, you’ll end up with a zip item that contains five items. Let’s verify this by zipping two lists of different lengths:

How to zip two lists of the same length in Python?

The following syntax shows how to zip together two lists of equal length into a dictionary: #define list of keys and list of values keys = ['a', 'b', 'c'] values = [1, 2, 3] #zip the two lists together into one dictionary dict (zip(keys, values)) {'a': 1, 'b': 2, 'c': 3} Example 3: Zip Two Lists of Unequal Length

What happens when you Zip a list with different length?

Zipping lists of unequal or different lengths results in a zip object that is as long as the shortest iterable in the items being passed in. This means, that if you pass in a list that is 5 items long, and another list that is one million items long, you’ll end up with a zip item that contains five items.

How to zip two lists of equal length into a dictionary?

The following syntax shows how to zip together two lists of equal length into a dictionary: If your two lists have unequal length, zip () will truncate to the length of the shortest list: If you’d like to prevent zip () from truncating to the length of the shortest list, you can instead use the zip_longest () function from the itertools library.


2 Answers

The method you are looking for is .zipAll:

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 takes 3 arguments:

  • the iterable to zip with
  • the default value if this (the collection .zipAll is called on) is shorter
  • the default value if the other collection is shorter
like image 58
Marth Avatar answered Oct 23 '22 22:10

Marth


The API-based zipAll is the way to go, yet you can implement it (as an exercise) for instance as follows,

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

Hence for instance

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

and

list1.zipAll2(list2, "", "") List((a,x), (b,y), (c,"")) 

A recursive version,

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

with default xd and default yd values.

like image 42
elm Avatar answered Oct 24 '22 00:10

elm