Trong Clojure có cách nào dễ dàng để chuyển đổi giữa các loại danh sách không?


92

Tôi thường thấy mình đang sử dụng danh sách lười biếng khi tôi muốn một vectơ và ngược lại. Ngoài ra, đôi khi tôi có một vector bản đồ, khi tôi thực sự muốn có một bộ bản đồ. Có bất kỳ chức năng trợ giúp nào để giúp tôi chuyển đổi giữa các loại này không?

Câu trả lời:


146

Đừng quên rằng cái cũ đáng tin cậy intocho phép bạn lấy bất cứ thứ gì seqcó thể (danh sách, vectơ, bản đồ, tập hợp, bản đồ được sắp xếp) và một vùng chứa trống mà bạn muốn lấp đầy và đặt intonó.

(into [] '(1 2 3 4)) ==> [1 2 3 4]         "have a lazy list and want a vector"
(into #{} [1 2 3 4]) ==> #{1 2 3 4}        "have a vector and want a set"
(into {} #{[1 2] [3 4]}) ==> {3 4, 1 2}    "have a set of vectors want a map"
(into #{} [{1 2} {3 4}]) ==> #{{1 2} {3 4}} "have a vector of maps want a set of maps"

intolà một trình bao bọc xung quanh conj, là phần trừu tượng cơ sở để chèn các mục nhập mới một cách thích hợp vào một tập hợp dựa trên loại tập hợp. Nguyên tắc làm cho dòng chảy này trở nên độc đáo là Clojure được xây dựng dựa trên sự trừu tượng có thể kết hợp , trong trường hợp này intoconjtrên đầu trang của bộ sưu tập và seq.

Các ví dụ trên sẽ vẫn soạn tốt nếu người nhận được chuyển vào lúc chạy: bởi vì các phần trừu tượng cơ bản ( seqconj) được triển khai cho tất cả các tập hợp (và nhiều tập hợp của Java cũng vậy), vì vậy các phần trừu tượng cao hơn không cần phải lo lắng về rất nhiều trường hợp góc liên quan đến dữ liệu đặc biệt.


3
1 cho vào ... đáng chú ý là nó cũng làm việc với những người không có sản phẩm nào bao bì xuất xứ cũng như (tức là khi bạn muốn thêm vào một bộ sưu tập)
mikera

11
Cũng cần lưu ý rằng bởi vì intosử dụng conj, thực hiện (into '() some-seq)sẽ mang lại một danh sách, ngược lại với một số seq, bởi vì conjliên quan đến danh sách.
Chuck

Cần lưu ý rằng intosử dụng quá độ (đối với hầu hết các loại seq) để có các đặc điểm hiệu suất tốt hơn hầu hết các phương tiện chuyển đổi khác.
Jarred Humphrey

Và nó hiện đang làm việc với bộ chuyển đổi, mà không tồn tại vào thời điểm câu trả lời này đã được viết (Tôi không biết nếu quá độ đã làm một trong hai) (Câu trả lời này là đủ tuổi để ghi danh vào mẫu giáo)
Arthur Ulfeldt

33

vec, setvà nói chung intolà những người bạn của bạn để dễ dàng "chuyển đổi" sang loại bộ sưu tập khác.

Làm thế nào để bạn muốn chuyển đổi một vectơ bản đồ thành một bản đồ? Bạn cần một khóa, bạn có thể cung cấp việc sử dụng với đầu vào mẫu / đầu ra dự kiến ​​không?


Xin lỗi, tôi có nghĩa là một tập hợp các bản đồ .. Tôi đã sửa đổi câu hỏi bây giờ
appshare.co

22

Đối với vectơ có vechàm

user=> (vec '(1 2 3))
[1 2 3]

Đối với các chuỗi lười biếng có lazy-seqchức năng

user=> (lazy-seq [1 2 3])
(1 2 3)

Để chuyển đổi thành tập hợp, có setchức năng

user=> (set [{:a :b, :c :d} {:a :b} {:a :b}])
#{{:a :b} {:a :b, :c :d}}

4
Khi bạn có một cái gì đó không lười biếng gọi lazy-seqthay vì seqchỉ thêm một hướng dẫn vô ích. Nếu bạn thực sự muốn trả lại một cái gì đó không phải là con số không, thậm chí còn trống rỗng mà vẫn có sequence. lazy-seqlà một cấu trúc cấp thấp.
cgrand

14

Một câu trả lời nữa cho việc chuyển đổi từ danh sách thành bản đồ (vì mục đích đầy đủ) - từ đây :

(apply hash-map '(1 2 3 4))
;=>{1 2, 3 4}

9

Để chuyển đổi một vectơ thành một danh sách, bạn cũng có thể sử dụng for, như sau:

=> (for [i [1 2 3 4]] i)
(1 2 3 4)

Khi bạn không muốn thao tác dữ liệu, chỉ cần sử dụng seqtrên vectơ:

=> (seq [1 2 3])
(1 2 3)

Thay vì forbạn chỉ có thể làm(map identity [1 2 3 4])
siltalau

7

Không cần phải chuyển đổi một vector thành một danh sách. Clojure sẽ coi một vectơ như nó sẽ coi một danh sách - như một chuỗi - khi một chuỗi được yêu cầu. Ví dụ,

user=> (cons 0 [1 2 3])
(0 1 2 3)

Nếu bạn cần đảm bảo rằng vectơ đang được coi là một chuỗi, hãy bọc nó trong seq:

user=> (conj [1 2 3] 0) ; treated as a vector
[1 2 3 0]

user=> (conj (seq [1 2 3]) 0) ; treated as a sequence
(0 1 2 3)

Nếu bạn có một vectơ bản đồ và bạn muốn một tập hợp các bản đồ, thì vectơ đó chứa các bản đồ không quan trọng. Bạn chỉ cần chuyển đổi vector thành một tập hợp như bình thường:

user=> (set [{:a 1, :b 2} {"three" 3, "four" 4}])
#{{:a 1, :b 2} {"four" 4, "three" 3}}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.