Yoink
Yoink

Reputation: 197

Scheme recursive unzip function for more than one list

I need help finishing up an unzip function which takes a zipped list and returns a list of two lists. The result I want is as follows...

(unzip '((a b) (1 2)))
'((a 1) (b 2))

(unzip '((a 1) (b 2) (c 3)))
'((a b c) (1 2 3))

(unzip '(unzip '()))
'(() ())

I can get my code to work for the null case and with a list containing two lists, but I'm having a hard time figuring out how to make it recursive and work for more than 2 lists such as the second example.

(define (unzip l)
  (if (null? l) 
      '(() ())
      (map list (car l) (car (cdr l)))))

This will work fine for an empty list or two lists, but I have a hard time setting up the recursive part to work with three or possibly more lists.

Upvotes: 0

Views: 2024

Answers (3)

GoZoner
GoZoner

Reputation: 70135

Are you aware that in Scheme a function can return multiple values?

(define (unzip list)
  (values (map car  list)
          (map cadr list)))

and then use it like this:

(let-values ([(z1 z2) (unzip '((a 1) (b 2)))])       
   ;; Use z1 and z2
   ...)

Upvotes: 0

Óscar López
Óscar López

Reputation: 235994

This is a pretty standard operation, it's equivalent to finding the transpose of a list of lists. It's usually implemented like this:

(define (unzip lst)
  (apply map list lst))

It'll work for the first two examples. The third, I believe is ill-defined, but if you want to make it work for that weird case, I'll leave that as an exercise ;)

Notice that if you unzip an unzipped list you get back the original input ... meaning that unzip is also zip!

(unzip '((a b) (1 2) (x y)))
=> '((a 1 x) (b 2 y))

(unzip '((a 1 x) (b 2 y)))
=> '((a b) (1 2) (x y))

Upvotes: 4

Will Ness
Will Ness

Reputation: 71065

(apply map list '((a 1) (b 2) (c 3) (d 4) (e 5)))

;Value 16: ((a b c d e) (1 2 3 4 5))

this does it. BTW the same trick does it for zipping as well, provided all the lists are of the same length:

(apply map list (list '(a b c d e) '(1 2 3 4 5)))

;Value 17: ((a 1) (b 2) (c 3) (d 4) (e 5))

Upvotes: 1

Related Questions