2009-06-09 24 views
11

Hàm Emacs Lisp sau đây lấy danh sách các danh sách và trả về một danh sách trong đó các mục trong danh sách bên trong đã được nối với một danh sách lớn. Nó là khá thẳng về phía trước và tôi tin rằng một cái gì đó như thế này phải là một phần của thư viện chức năng tiêu chuẩn.Tên của chức năng này trong thư viện Emacs Lisp cài sẵn?

(defun flatten (LIST) 
    (if LIST 
     (append (car LIST) (flatten (cdr LIST))) 
    nil)) 

Tôi đang tìm một hàm sẽ lấy một danh sách danh sách duy nhất làm đối số và sau đó nối thêm tất cả các danh sách bên trong.

(flatten '((a b) (c d))) 

sẽ cho

(a b c d) 

Có ai biết chức năng này đã được xây dựng trong, và nếu như vậy, theo đó tên?

Cảm ơn!

Trả lời

8

Bạn đang tìm kiếm hoặc append:

 
(defun flatten (list-of-lists) 
    (apply #'append list-of-lists)) 

Nếu (và chỉ nếu) bạn biết rằng bạn sẽ luôn có một danh sách liệt kê.

Nếu không:

 
(defun flatten (list) 
    (mapcan (lambda (x) (if (listp x) x nil)) list)) 
+1

Cảm ơn rất nhiều câu trả lời của bạn, các định nghĩa rất thanh lịch. Nhưng dù sao, câu hỏi của tôi không phải là quá nhiều cho một cách để đạt được hành vi này, nhưng liệu ELisp đã cung cấp một chức năng như vậy chưa. Điều này thực sự là nhiều hơn tò mò, không phải vì tôi phải đối mặt với một vấn đề cụ thể mà có vẻ rất phức tạp ... –

+3

Câu trả lời là, "có, nó", cụ thể là mapcan trên chức năng nhận dạng. – jrockway

+1

Tôi không nghĩ như vậy: mapcan có hai đối số (chức năng nhận dạng và danh sách) trong khi nghi ngờ "flatten" chỉ có một danh sách. (Curry ở đâu khi anh cần anh ta?) Dù sao, như tôi đã nói trước đây, nó không thực sự quan trọng, và các giải pháp của vatine ở trên đều tuyệt vời. –

0

Có một cái nhìn tại nconc

+0

'nconc' là phá hoại. –

+0

Vâng, đó là hầu như những gì tôi đang tìm kiếm. Sự khác biệt duy nhất là thay vì lấy danh sách các danh sách làm tham số, nconc lấy một số danh sách biến mà sau đó nó sẽ làm phẳng. Nhưng tôi nghĩ điều đó là đủ tốt, mặc dù như Gareth đã chỉ ra, người ta phải nhận thức được rằng nconc là phá hoại. – Thomas

6

tôi bước vào này chỉ thời gian gần đây trong khi tìm kiếm một cái gì đó khác nhau; có cái gì đó có thể không được đưa vào bằng chứng bởi dữ liệu thử nghiệm được sử dụng để kiểm tra hàm, tùy thuộc vào câu hỏi ban đầu có nghĩa là tham khảo danh sách chung (ví dụ: danh sách danh sách danh sách ...) hay chỉ với các danh sách hai cấp (như trong ví dụ).

solution based on append chỉ hoạt động tốt với danh sách hai cấp và có vấn đề khác với solution based on mapcan.

Về cơ bản, giải pháp chung phải được đệ quy cả trên xe hơi và cdr, như trong các flatten defun dưới đây.

(setq l '((((1 2) 3) 4) (5 6 7))) 

(defun flatten(x) 
    (cond ((null x) nil) 
    ((listp x) (append (flatten (car x)) (flatten (cdr x)))) 
    (t (list x)))) 

(defun flatten2(l) 
    (if l (append (car l) (flatten2 (cdr l))) nil)) 

(defun flatten3(l) 
    (mapcan (lambda(x) (if (listp x) x nil)) l)) 

(flatten l) 
(1 2 3 4 5 6 7) 

(apply #'append l) 
(((1 2) 3) 4 5 6 7) 

(flatten2 l) 
(((1 2) 3) 4 5 6 7) 

Vấn đề nữa là với việc sử dụng mapcan trong flatten3: như mapcan ẩn một nconc bên trong, người dùng phải nhớ rằng nó làm thay đổi đối số của nó.

l 
((((1 2) 3) 4) (5 6 7)) 

(flatten3 l) 
(((1 2) 3) 4 5 6 7) 

l 
((((1 2) 3) 4 5 6 7) (5 6 7)) 
+0

Phản hồi rất tốt, cảm ơn bạn. – re5et

2

Tôi nhận ra rằng câu hỏi ban đầu là "chức năng dựng sẵn" là gì. Có vẻ như không có. Các giải pháp khác không thực sự làm phẳng tất cả các danh sách mà tôi đã thử nghiệm. Chức năng này dường như hoạt động. Tôi đăng nó ở đây vì đây là nơi đầu tiên Google đánh khi tôi tìm kiếm.

(defun flatten (LIST) 
    "flattens LIST" 
    (cond 
    ((atom LIST) (list LIST)) 
    ((null (cdr LIST)) (flatten (car LIST))) 
    (t (append (flatten (car LIST)) (flatten (cdr LIST)))))) 

ví dụ:

(flatten (list "a" (list "b" "c" nil) (list (list "d" "e") "f"))) 
("a" "b" "c" nil "d" "e" "f") 
3

Dash là thư viện danh sách hiện đại cho Emacs và đã san bằng. Đây là gói phần mềm được tải xuống nhiều nhất thứ hai trên Melpa, sau khi sử dụng.Từ số readme:

-flatten (l): Lấy danh sách lồng nhau l và trả về nội dung của nó dưới dạng danh sách đơn, phẳng.

(-flatten '((1))) ;; => '(1) 
(-flatten '((1 (2 3) (((4 (5))))))) ;; => '(1 2 3 4 5) 
(-flatten '(1 2 (3 . 4))) ;; => '(1 2 (3 . 4)) 

-flatten-n (num list): Flatten num mức của danh sách lồng nhau.

(-flatten-n 1 '((1 2) ((3 4) ((5 6))))) ;; => '(1 2 (3 4) ((5 6))) 
(-flatten-n 2 '((1 2) ((3 4) ((5 6))))) ;; => '(1 2 3 4 (5 6)) 
(-flatten-n 3 '((1 2) ((3 4) ((5 6))))) ;; => '(1 2 3 4 5 6) 

Gói này bắt đầu 2012-09.

Các vấn đề liên quan