Как я могу вернуть список с разными значениями? - PullRequest
4 голосов
/ 01 января 2012

Если у меня есть следующий список:

(define thelist '(0 1 0 0 7 7 7))

Как мне написать функцию, которая возвращает новый список, в котором заменяется значение в запрошенной ячейке.

Пример:

(set-cell thelist 2 4)

Это вернет новый список с теми же значениями, но в ячейке (2) будет значение 4 вместо 1:

(0 4 0 0 7 7 7)

Ответы [ 5 ]

5 голосов
/ 01 января 2012

HtDP предоставляет действительно конкретную методологию для решения такого рода проблем. Для этой проблемы ваша задача будет записать шаблон для списков, а затем смотреть на него, пока вы не увидите, какими должны быть аргументы рекурсивного вызова и каковы будут результаты. Я надеюсь, что вы решили кучу проблем с прогревом в списках - вычислите длину списка, посчитайте количество 6 в списке и т. Д.

4 голосов
/ 01 января 2012

Хотя вы можете реализовать запрошенную функциональность со списками, естественным способом решения этой проблемы является использование vector, и помните, что в Схеме индексы начинаются с 0 (поэтому второй аргумент дляvector-set! - это 1, а не 2):

(define thevector (vector 0 1 0 0 7 7 7))
; thevector is #(0 1 0 0 7 7 7)
(vector-set! thevector 1 4)
; thevector is #(0 4 0 0 7 7 7)

Теперь, если вам определенно нужно использовать список, что-то вроде этого будет работать:

(define (set-cell lst idx val)
  (cond ((null? lst) '())
        ((zero? idx) (cons val (cdr lst)))
        (else (cons (car lst)
                    (set-cell (cdr lst) (sub1 idx) val)))))

И вы бы назвали это так:

(define thelist '(0 1 0 0 7 7 7))
(set-cell thelist 1 4)
> (0 4 0 0 7 7 7)

Опять же, я использую индексирование на основе 0, как это принято.Также обратите внимание, что thelist был не изменен, вместо этого set-cell возвращает новый список с модификацией.

0 голосов
/ 27 марта 2012

Вот подход, использующий вспомогательную функцию, которая начинает счет с 0. При каждой рекурсии счет увеличивается, а список укорачивается.

Если выбран нужный индекс, рекурсия может быть остановлена.Если он попадает в конец списка без попадания в индекс, возвращается исходный список.

(define (set-cell ls ind val)

  (define (aux c ls)
    (cond ((null? ls) ls)
          ((= c ind) (cons val (cdr ls)))
          (else (cons (car ls) (aux (+ c 1) (cdr ls))))))

  (aux 0 ls))
0 голосов
/ 03 января 2012

Другие люди упомянули соглашение об индексах на основе 0.Тогда я буду считать индексы, основанные на 0.

Другие полученные вами ответы неверны, учитывая то, как вы сформулировали свою проблему.Я приведу ключевой момент в вашем вопросе (мой акцент):

Это вернет новый список с теми же значениями, но в ячейке (2) будетзначение 4 вместо 1.

Ответы, которые вы получили, модифицируют список на месте, не возвращая вновь созданный список, оставляя исходный нетронутым!

Вотправильное (хотя и неоптимальное) решение:

(define (set-list index new-value list)
  (if (= index 0)
      (cons new-value (cdr list))
      (cons (car list)
            (set-list (- index 1) new-value (cdr list))))))

Я не удосужился поставить здесь проверку на ошибки (например, если кто-то перейдет в пустой список или список, содержащий слишком мало элементов относительно indexили отрицательный индекс).

0 голосов
/ 02 января 2012

Какой беспорядок выше !! Сохраняйте это простым: схема имеет список-набор! за это. Пример:

(define ls (list 1 2 3 4 5))
(list-set! ls 0 "new")
(list-set! ls 3 "changed")
(list-ref ls 0)
  => "new"
ls
  => '("new" 2 3 "changed" 5)

Однако вы можете ограничить назначения в списках. Векторы быстрее для этого, так как вам не нужно пересекать предыдущие элементы. Используйте списки всякий раз, когда вы не можете указать длину перед построением или когда длина постоянно изменяется.

...