0

I have 2 numbers let's say number1=5 and number2=3 and I want to create a list in this form

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

So the number1 indicates the number of the elements in the list and number2 indicates the total elements that will be as the second part of every element..

I have smth like this untill now

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

Unfortunately it doesn't work.. It doesn't give the result I want.. It gives me this (((((((((((((((() (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))

4

2 回答 2

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

现在,一个更惯用的解决方案是使用高阶过程。这将在球拍中工作:

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

看看我们如何避免显式循环?这就是 Scheme 的思维方式,也是你解决问题的方式——拥抱它!

于 2013-11-13T17:50:35.007 回答
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 的回答为这个问题提供了一种更惯用的方法。这是一个类似的惯用方法:

(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)))
于 2013-11-13T17:50:08.690 回答