重写列表列表中的项目

Rewrite an item in a list of list

这看起来很简单,但我似乎找不到解决方案。我想用某些东西替换列表列表中的一个项目, 但是 如果该项目出现多次,那么你随机替换其中一个,但不能同时替换两个。我想在 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) 可能 return 这个或任何其他 '- 所在的位置:

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

我已经研究了一段时间,所以任何新的见解都会有很长的路要走。谢谢

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

(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? 比较结构。

不是随机的。它将通过在 cdr 之前执行 car 或在 car.

之前执行 cdr 来替换它找到的第一次出现

"random" 部分是导致此问题病态的原因。如果您可以只替换 first 的出现,那将很容易。但是要替换一个 random 的出现,你必须首先知道有多少次出现。所以在你去更换东西之前,你必须去数数:

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