как да игнорирам вътрешните списъци в схемата?

Написах процедура, която получава всяка стойност от списък и връща списък, където всяка стойност е -1 (например)

(define (Set-list a val)
  (if ( null? a) (list)
    (append (list val) (Set-list (cdr a) val))
))

(Set-list '(2 3 4) -1) //returns '(-1 -1 -1)
(Set-list '(A(2 3) B(2 3) C(2 3)) -1) // returns '(-1 -1 -1 -1 -1 -1)

как да го накарам да върне -1 -1 -1? Не искам да получавам вътрешните членове на списъка?


person Ivan Prodanov    schedule 13.01.2013    source източник
comment
Само за да сте сигурни, че разбирате вашия пример: мислите ли, че A(2 3) е единичен външен елемент с някои елементи вътре? (Това наистина са два външни елемента, символът A и списъкът (2 3). Искате ли да пропуснете елементи, които самите са списъци?)   -  person Anton Kovalenko    schedule 13.01.2013


Отговори (4)


Тъй като Антон спомена за идиоматично решение, ето моето идиоматично решение в Racket (вярвам, че използването на функции от по-висок ред, като map, filter-not и може би const е по-идиоматично от ръчното зацикляне и филтриране). :-)

(define (set-list lst val)
  (map (const val) (filter-not list? lst)))

(Racket предоставя filter-map, но прилага filter и map в ред, обратен на това, което искаме да направим.)

person Chris Jester-Young    schedule 13.01.2013

Може би обърквате как работят списъците в Scheme. Този списък: '(A(2 3) B(2 3) C(2 3)) е точно същият като този списък: '(A (2 3) B (2 3) C (2 3)). Тоест, това е списък от шест елемента. Ако искате да третирате комбинацията от символ-и-числа като един елемент, опаковайте ги заедно в един списък: '((A 2 3) (B 2 3) (C 2 3))

Като странична бележка, начинът, по който е написана процедурата set-list, не е идиоматичен, по-специално използването на append не е най-добрият начин за поставяне на елементи в началото при изграждане на списък, използвайте cons за това. Това е по-добрият начин да напишете процедурата:

(define (set-list a val)
  (if (null? a)
      '()
      (cons val
            (set-list (cdr a) val))))

Сега, следвайки съвета ми по-горе, ето как ще работи:

(set-list '((A 2 3) (B 2 3) (C 2 3)) -1)
=> '(-1 -1 -1)

АКТУАЛИЗАЦИЯ:

Сега, ако наистина няма недоразумение с начина, по който списъците работят и просто искате да замените всички подсписъци в списък с дадена стойност, това ще работи:

(define (set-list a val)
  (build-list (length (filter (negate list?) a))
              (lambda (x) val)))
person Óscar López    schedule 13.01.2013
comment
OP не изглежда да е объркан, вижте коментарите. Той просто иска изцяло да пропусне подсписъците. (Мога да опитам да го напиша, но няма да е идиоматична схема, може би вие?) - person Anton Kovalenko; 13.01.2013

Ето моя опит (вероятно не идиоматична схема и моля, имайте предвид, че да го правите с append така или иначе е грешно). Предполагам, че искате да пропуснете изцяло подсписъците, както обяснихте в коментарите.

(define (Set-list a val)
  (if (null? a)
      (list)     
      (append (if (list? (car a))
                  (list)
                  (list val))
              (Set-list (cdr a) val))))
person Anton Kovalenko    schedule 13.01.2013
comment
Вие сте близо. Ако базирате подхода си на cons вместо на append, вашето решение би било доста идиоматично, поне извън набора от решения, които не използват функции от по-висок ред. (Вижте публикацията ми за решение, базирано на функция от по-висок порядък.) - person Chris Jester-Young; 13.01.2013

Ако искате да направите списък със стойности, чиято дължина е еднаква с дадена дължина на списъците,

(define (set-list list value)
    (build-list (length list) (lambda (x) value)))

so,

(set-list '(2 3 4) -1) //returns '(-1 -1 -1)
(set-list '(A (2 3) B (2 3) C (2 3)) -1) // returns '(-1 -1 -1 -1 -1 -1)
(set-list '(2 3 4) -2) //returns '(-2 -2 -2)
(set-list '(A (2 3) B (2 3) C (2 3)) -2) // returns '(-2 -2 -2 -2 -2 -2)
person grgizem    schedule 02.02.2013