重写列表列表中的项目

时间:2015-03-29 01:16:34

标签: scheme racket

这似乎很简单,但我似乎无法找到解决方案。我想用列表替换列表列表中的项目,如果该项目多次出现,则随机替换其中一项,但不能同时替换两者。我想在ISL +中这样做。

我创建了flatten函数,它附加了所有子列表:

(check-expect (flatten '((a b) (c) (d e f g) (h i j)))
              (list 'a 'b 'c 'd 'e 'f 'g 'h 'i 'j))
(define (flatten lol)
  (foldr append empty lol))

我也做了重写,用你选择的任何东西替换索引n的值

(check-expect (rewrite '(x x x - x x x x) 3 'x)
              (list 'x 'x 'x 'x 'x 'x 'x 'x))
(define (rewrite ls n val)
  (cond 
    [(empty? ls) (error "error")]
    [(= n 0) (cons val (rest ls))]
    [else (cons (first ls) (rewrite (rest ls) (sub1 n) val))]))

问题是我不知道如何将其应用到列表列表中,如果多次出现,我也不知道如何随机替换其中一个项目。这就是我对最终产品所拥有的,但它可能不是最佳选择:

(define (fullreplace b)
  (local [ 
;makes a list of nested lists of each index the element occurs
;problem is that it makes a list of nested lists so I can't use flatten either
(define (position ls ele n)
  (cond [(empty? ls) 0]
        [(equal? ele (first ls)) (list n (position (rest ls) ele (add1 n))) ]
        [else (position (rest ls) ele (+ 1 n))]))]
;lol-full? checks if the item occurs in the list of lists at all
    (if (lol-full? b) b  (rewrite (flatten b) 
                                       (position (flatten b) '- 0)
                                       "item replaced"))))
;just used for testing 
(define lol2 (list
            (list 2 2 2 2)
            (list 4 '- 4 '-)
            (list '- 8 8 8)
            (list 16 '- '- 16)))

(fullreplace lol2)可能会返回此内容或其他任何位置:

(list
 (list 2 2 2 2)
 (list 4 '- 4 2)
 (list '- 8 8 8)
 (list 16 '- '- 16))

我一直在努力工作,所以任何新的见解都会有很长的路要走。谢谢

2 个答案:

答案 0 :(得分:2)

"随机"部分是使这个问题病态的原因。如果您只是替换第一个事件,那将很容易。但要替换随机出现,您必须首先知道有多少次出现。因此,在你更换东西之前,你必须进行计算:

(define (count/recursive val tree)
  (cond ((equal? val tree)
         1)
        (else (foldl (λ (next-value total)
                       (cond ((equal? val next-value)
                              (add1 total))
                             ((list? next-value)
                              (+ total (count/recursive val next-value)))
                             (else total))) 0 tree))))

然后你需要一个可以替换第n次出现的函数:

(define (replace/recursive val replace-with n tree)
  (cond ((equal? val tree)
         replace-with)
        (else
         (cdr
           (foldl (λ (next-value total/output-tree)
                    (local ((define total (car total/output-tree))
                            (define output-tree (cdr total/output-tree)))
                      (cond ((equal? next-value val)                                  
                             (cons (add1 total)
                                   (cons (if (= total n) replace-with next-value) output-tree)))
                            ((list? next-value)
                             (cons (+ total (count/recursive val next-value))
                                   (cons (replace/recursive val replace-with (- n total) next-value) 
                                         output-tree)))
                            (else (cons total (cons next-value output-tree)))))) (cons 0 empty) tree)))))

最后,您使用random选择要替换的实例,使用count/recursive来限制random次选择的数量:

(define original '((x x (x y x) a b (((c x z x) x) y x x))))
(replace/recursive 'x '- (random (count/recursive 'x original)) original)

答案 1 :(得分:1)

如何用另一个值替换值的所有出现:

(define (replace-all needle new-value haystack)
  (cond ((equal? needle haystack) new-value)
        ((pair? haystack) 
         (cons (replace-all needle new-value (car haystack))
               (replace-all needle new-value (cdr haystack))))
        (else haystack)))

唯一要改变的是检查第一部分是否构成变化。如果它确实你没有在另一半做替换。使用equal?来比较结构。

随机。它会在carcdrcdr之前car替换它找到的第一个出现。