简体   繁体   中英

Scheme Inverse List Function

I defined a function called zip which took two lists as parameters and returned a list of pairs.

(define (zip list1 list2)
(if (null? list1)
  '()
   (cons (list (cons (car list1) (car list2)))
            (zip (cdr list1) (cdr list2)))))

(zip (list 1 3 5) (list 2 4 6))
> (((1 . 2)) ((3 . 4)) ((5 . 6)))

Now I'm basically having trouble writing the inverse function of this. This is what I have so far. This function needs to output a list of two lists. I only attempted at making the first of the two lists to make it easier for myself but the output is not what I want.

(define (unzip u-list)
  (if (null? u-list)
      '()
       (list (car (car (car u-list))) (unzip(cdr u-list)))))


(unzip (zip (list 1 3 5) (list 2 4 6)))
> (1 (3 (5 ())))

Any help would be appreciated...

I believe there's a problem with your implementation of zip , did you notice that you're returning a list of single-element lists of pairs? returning a list of pairs makes more sense:

(define (zip lst1 lst2)
  (if (null? lst1)
      '()
      (cons (cons (car lst1) (car lst2))
            (zip (cdr lst1) (cdr lst2)))))

Or even better, let's use the map higher-order function for a shorter, more idiomatic solution:

(define (zip lst1 lst2)
  (map cons lst1 lst2))

Regarding unzip : it's easier if we split the problem in parts - let's get the first element of each pair, then the second element of each pair, and finally build a list with the answer. Try this:

(define (unzip lst)
  (define (firsts lst)
    (if (null? lst)
        '()
        (cons (caar lst)
              (firsts (cdr lst)))))
  (define (seconds lst)
    (if (null? lst)
        '()
        (cons (cdar lst)
              (seconds (cdr lst)))))
  (list (firsts lst) (seconds lst)))

But once again, we're reinventing the wheel. Let's just use built-in functions to write a simpler answer:

(define (unzip lst)
  (list (map car lst) (map cdr lst)))

Anyway, now unzip is the inverse of zip :

(zip '(1 3 5) '(2 4 6))
=> '((1 . 2) (3 . 4) (5 . 6))

(unzip '((1 . 2) (3 . 4) (5 . 6)))
=> '((1 3 5) (2 4 6))

As you make it with pairs it's somewhat more difficult but not much:

(define (zip-pair a b)
  (map cons a b))

(define (unzip-pair zipped-pair)
  (list (map car zipped-pair) 
        (map cdr zipped-pair)))

zip is usually implemented with apply and map and takes list and produce list of lists, like this:

(define (zip . lists)
  (apply map list lists))

(zip '(1 2 3) '(a b c)) ; ==> ((1 a) (2 b) (3 c))

Though this will make lists and not pairs. However a unzip is almost the same except that you will take a list of lists instead of variable number of arguments:

(define (unzip1 zipped-list)
  (apply map list zipped-list))

; or reuse zip
(define (unzip1 zipped-list)
  (apply zip zipped-list))

(unzip1 '((1 a) (2 b) (3 c))) ; ==> ((1 2 3) (a b c))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM