从2个数字和2个循环创建列表

时间:2013-11-13 17:18:14

标签: list loops scheme

我有2个数字,我们说number1 = 5,number2 = 3,我想以这种形式创建一个列表

(p(1(1 2 3))(2(1 2 3))(3(1 2 3))(4(1 2 3))(5(1 2 3)))

因此number1表示列表中元素的数量,number2表示将作为每个元素的第二部分的总元素。

我现在已经这样了,直到现在

(define mylist '())

   (define (pushlist item item2)
  (do ((j 1 (+ j 1))) ((> j item2))
   (set! mylist(list mylist (list item j)))))



  (define (createlist number number2)
   (do ((j 1 (+ j 1))) ((> j number))
   (pushlist j number2)
    ))

  (createlist 5 3)

不幸的是它不起作用..它没有给出我想要的结果..它给了我(((((((((((((((() (1 1)) (1 2)) (1 3)) (2 1)) (2 2)) (2 3)) (3 1)) (3 2)) (3 3)) (4 1)) (4 2)) (4 3)) (5 1)) (5 2)) (5 3))

2 个答案:

答案 0 :(得分:1)

有许多方法可以解决此问题 - 例如,使用显式递归或使用高阶过程。不推荐您的方法,在Scheme中,您应该尽量避免考虑循环和变异操作。虽然 可以编写这样的解决方案,但它不会是惯用的。我将首先尝试使用显式递归来解释如何编写更惯用的解决方案:

; create a list from i to n
(define (makelist i n)
  (if (> i n)
      '()
      (cons i (makelist (add1 i) n))))

; create a list from i to m, together with
; a list returned by makelist from 1 to n
(define (makenumlist i m n)
  (if (> i m)
      '()
      (cons (list i (makelist 1 n))
            (makenumlist (add1 i) m n))))

; call previous functions
(define (createlist number1 number2)
  (makenumlist 1 number1 number2))

现在,一个更惯用的解决方案是使用更高阶的程序。这将适用于Racket:

; create a list from i to n
(define (makelist n)
  (build-list n add1))

; create a list from i to m, together with
; a list returned by makelist from 1 to n
(define (makenumlist m n)
  (build-list m
              (lambda (i)
                (list (add1 i) (makelist n)))))

; call previous functions
(define (createlist number1 number2)
  (makenumlist number1 number2))

了解我们如何避免显式循环?这就是计划的思维方式,你期望解决问题的方式 - 拥抱它!

答案 1 :(得分:0)

我不认为您的pushlist程序正在按照您的预期行事。

(define (pushlist item item2)
  (do ((j 1 (+ j 1)))
      ((> j item2))
    (set! mylist (list mylist (list item j)))))

如果您有一个列表(x y z),并且想要将新值v添加到其中,则可以

(set! lst (cons v lst))

因为(cons v (x y z)) == (v x y z)。通过做

(set! mylist (list mylist (list item j)))

你正在使mylist总是有两个元素,其中第一个是更深入和更深的嵌套列表。 Óscar López's answer为这个问题提供了更为惯用的方法。这是一种类似的惯用法:

(define (range n)
  ; returns a list (1 ... n)
  (let rng ((n n) (l '()))
    (if (zero? n) 
        l
        (rng (- n 1) (cons n l)))))

如果子列表(1 ... n)都可以是相同的列表(即实际列表对象是相同的),那么您只需创建一次:

(define (createlist m n)
  (let ((sublist (range n)))
    (map (lambda (main)
           (list main sublist))
         (range m))))

否则,如果需要区分,则可以为1 ... m生成一个:

(define (createlist m n)
  (map (lambda (main)
         (list main (range n)))
       (range m)))