带有可能不均匀列表的方案 zip 功能 [英] Scheme zip function with possible uneven lists

查看:40
本文介绍了带有可能不均匀列表的方案 zip 功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道以前有人问过这个问题,我的解决方案与许多答案相同,但我有一个特殊的测试用例,无法与此问题的通用解决方案一起正常工作.

I know this question has been asked before, and my solution is the same as many of the answers but I have a special test case that won't work correctly with the common solution to this problem.

我像许多其他人一样为 zip 问题找到的解决方案是

The solution that I have found for the zip problem like many others is

(define (zip l1 l2)(map list l1 l2))

... 用给定的参数很好用,比如

. . .which works great with given arguments such as

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

但我也希望 zip 函数适用于我的参数与

but I also want the zip function to work for cases where my arguments do not match length like

(zip '(a b c) '(1)) => ((a 1) (b ()) (c ()))

我还没有找到解决这个问题的方法,也不确定如何在每个列表可以是任意长度的情况下处理它.

I have not found a solution to this problem and not really sure how to approach it where each list can be any length.

推荐答案

首先,一个仅适用于 2 个列表的简单迭代版本:

First, a simple iterative version that works for 2 lists only:

(define (zip lst1 lst2 (placeholder '()))

  (define (my-car lst)
    (if (empty? lst) placeholder (car lst)))
  (define (my-cdr lst)
    (if (empty? lst) lst (cdr lst)))

  (let loop ((lst1 lst1) (lst2 lst2) (res '()))
    (if (and (empty? lst1) (empty? lst2))
        (reverse res)
        (loop (my-cdr lst1) (my-cdr lst2) 
              (cons (list (my-car lst1) (my-car lst2)) res)))))

比如

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

(zip '(a b c) '(1))
=> '((a 1) (b ()) (c ()))

由此,您可以推广到 n 个列表,但为了避免关键字参数,您必须首先放置占位符参数:

From this, you can generalise to n lists, but to avoid keyword parameters you have to put the placeholder parameter first:

(define (zip placeholder . lsts)

  (define (my-car lst)
    (if (empty? lst) placeholder (car lst)))
  (define (my-cdr lst)
    (if (empty? lst) lst (cdr lst)))

  (let loop ((lsts lsts) (res '()))
    (if (andmap empty? lsts)
        (reverse res)
        (loop (map my-cdr lsts) 
              (cons (apply list (map my-car lsts)) res)))))

比如

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

(zip '() '(a b c) '(1))
==> '((a 1) (b ()) (c ()))

(zip '() '(a b c) '(1) '(x y))
=> '((a 1 x) (b () y) (c () ()))

我相信 andmap 是这里唯一特定于 Racket 的函数,根据您的实现,它可能有一些 Scheme 或 SRFI 等效函数.

I believe that andmap is the only Racket-specific function here, which probably has some Scheme or SRFI equivalent depending on your implementation.

编辑

由于解决方案是基于创建等长的列表,而不是复制 zip 算法,您还可以在执行经典地图列表之前先将占位符添加到列表中:

Since the solution is based on creating lists of equal length, instead of duplicating the zip algorithm, you can also first add the placeholders to the lists before doing the classic map-list stuff:

(define (zip placeholder . lsts)
  (let* ((max-len (apply max (map length lsts))) ; the length of the longest lists
         (equal-length-lists                     ; adjusts all lists to the same length,
          (map                                   ;   filling with placeholder
           (lambda (lst) (append lst (make-list (- max-len (length lst)) placeholder)))
           lsts)))
    (apply map list equal-length-lists)))        ; classical zip

这篇关于带有可能不均匀列表的方案 zip 功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆