2016-12-09 5 views
2

Я пытаюсь создать конкретный ответ для данного списка, если он имеет общие элементы с другим списком. Как и в случае, если у меня есть список (мое имя - Джон), и у меня есть другой список (John Adam Jacob), я бы хотел, чтобы первый список мог видеть, что Джон во втором списке, и иметь возможность печатать что-то вроде (это известное имя) или что-то похожее.Racket найти общие элементы между списками

Код, о котором я думал, использует карту и член.

(define (specific-reply user-list) 
    (cond (member (map (lambda (user-list)) '(John Adam Jacob))) 
      (write (this is a known name)) 
     (else 
      (write (this is not a known name))))) 

Я очень знал, как рэкет и схемы, однако, и я действительно не получил его компилировать еще, так что я думаю, что я в основном прочь.

Любая помощь была бы принята с благодарностью.

ответ

2

Вам не нужно усложнять проблему, если ваша задача состоит в том, чтобы просто найти, если является членом (a b c),

Вот кусок схемы кода, который может сказать, если a является членом от lat. Это просто простая рекурсивная функция, которая сравнивает каждый элемент lat с a для соответствия.

(define member? 
    (lambda (a lat) 
     (cond 
      ((null? lat) #f) 
      ((eq? a lat) #t) 
      (else 
       (member? a (cdr lat)))))) 

Если вы хотите сделать это дальше и найти пересечение двух списков, мы можем сделать что-то подобное!

(define intersect 
    (lambda (set1 set2) 
      (letrec 
       ((I (lambda (set) 
         (cond 
          ((null? set) (quote())) 
          ((member? (car set) set2) 
          (cons (car set) 
            (I (cdr set)))) 
          (else (I (cdr set))))))) 
      (I set1)))) 

Вы можете использовать этот код как таковой. Испытано от лукавства компилятора

(begin 
     (display (intersect `(1 2 3) `(1 3 4 5 2))) 
     (newline)) 

>> (1 2) 

EDIT

Я рекомендую вам прочитать The Little Schemer и The Seasoned Schemer, чтобы получить больше знакомы с такого рода концепций

1

можно также использовать встроенные функции filter и member, чтобы найти пересечение из 2 списков:

(define (intersection l1 l2) 
    (remove-duplicates 
    (filter (λ (x) (member x l1)) 
      l2))) 

Выше проверяется каждый элемент l2, чтобы сохранить его, только если он является членом l1.

Можно также использовать for/list, чтобы проверить каждый элемент и возвращает список общих элементов:

(define (intersect l1 l2) 
    (remove-duplicates 
    (for/list ((i l1) 
       #:when (member i l2)) 
    i))) 

И выше функция удаления дубликатов. Просто избегать использования remove-duplicates может привести к разному результату, если просто выполняется порядок l1 и l2.Если кто-то хочет, чтобы повторяющиеся элементы прийти повторно в списке исходов, можно использовать следующую функцию, в которой общие элементы удаляются перед началом работы:

(define (intersection2 l1 l2) 
    (let loop ((l1 l1) 
      (l2 l2) 
      (ol '())) 
    (cond 
     [(empty? l1) (reverse ol)] 
     [(member (first l1) l2)  ; first item of l1 is common 
     (loop (rest l1)    ; loop with rest of l1 
      (remove (first l1) l2) ; remove common item from l2 
      (cons (first l1) ol))] ; add common item to outlist 
     [else 
     (loop (rest l1) 
      l2 
      ol)]))) 

Testing:

(intersection2 '(2 4 2 7 2 10) '(10 2 9 2 0 11)) 

Выход:

'(2 2 10) 
+0

'member' не является функцией более высокого порядка (по крайней мере, не тогда, когда используется без его дополнительного 3-го аргумента). –

+0

Я исправил заявление. – rnso

1

Почему бы не использовать set в ракетке:

(define (list-intersect-2 lst1 lst2) 
    (set->list 
    (set-intersect (list->set lst1) 
        (list->set lst2)))) 

Для решения, который принимает один или несколько списков:

(define (list-intersect lst1 . lstn) 
    (set->list 
    (foldl set-intersect 
      (list->set lst1) 
      (map list->set lstn)))) 


(list-intersect '(1 2 3) '(2 3 4) '(3 4 8)) 
; ==> (3) 
Смежные вопросы