2015-04-11 31 views
21

Giả sử tôi có một immutable.js List như thế này:Làm cách nào để chuyển Danh sách Maps thành Bản đồ của Maps trong immutable.js?

var xs = Immutable.fromJS([{key: "k", text: "foo"}]) 

Tôi muốn chuyển đổi đó vào một bản đồ mà trông như thế này:

var ys = Immutable.fromJS({k: {key: "k", text: "foo"}}) 

Làm thế nào để biến xs vào ys idiomatically trong bất biến .js?

By idiomatically Tôi có nghĩa là bất kỳ cấu trúc trung gian nên các cấu trúc immutable.js, và tôi nghĩ rằng bất kỳ bước trung gian sẽ sử dụng iterable composition thay vì tạo kích thước đầy đủ đại diện trung gian.

Chỉnh sửa: Tôi đã tạo một jsperf benchmark so sánh các câu trả lời được cung cấp cho đến thời điểm này. Cả hai giải pháp không biến đổi cảm thấy khá thành ngữ với tôi; Tôi có thể nắm giữ và để cho các lá phiếu quyết định câu trả lời đã chọn hoặc giữ cho đến khi chúng tôi có thể thu thập một bộ sưu tập các kỹ thuật thành ngữ gần như bằng nhau.

+0

Bạn có thực sự muốn Bản đồ các bản đồ hay bạn muốn Bản đồ các đối tượng không? – Bergi

+1

@Bergi Bản đồ của Bản đồ - không thay đổi được hết. –

Trả lời

2

Có vẻ như thế này, nhưng tôi không chắc chắn về cơ quan đại diện trung gian

ys = Immutable 
    .fromJS([{key:'k', value:'xxx'}]) 
    .toKeyedSeq() 
    .mapEntries(function (kv) { return [kv[1].get('key'), kv[1]]; }) 

PS Đó là lạ, nhưng tôi chỉ có thể sử dụng .toKeyedSeq, không .toKeyedIterable, đó là thích hợp hơn.

20

Bạn có thể giảm danh sách đầu vào Immutable.Map mới:

var ys = xs.reduce(
     function(result, item) { return result.set(item.get('key'), item); }, 
     Immutable.Map()); 

Không có đại diện trung gian trong trường hợp này, nhưng bản đồ bất biến đã được cập nhật (trên thực tế, ví dụ mới phải được tạo ra) trong mỗi lần lặp lại và điều đó có thể được tối ưu hóa (tùy thuộc vào việc thực hiện thực tế của Immutable.Map).

Bạn có thể tối ưu hóa nó giảm vào đối tượng javascript thường xuyên và chuyển nó sang bản đồ bất biến ở cuối:

var ys = Immutable.Map(xs.reduce(
     function(result, item) { result[item.get('key')] = item; return result; }, 
     {})); 

Nhưng đó chắc chắn ít thành ngữ là.

+0

Cảm ơn bạn đã trả lời hợp lý! Tôi nghĩ đây là câu trả lời hay nhất. Nhưng khi tôi so sánh hiệu suất cập nhật Bản đồ ở mỗi lần lặp lại và xây dựng một bản đồ mới ở cuối, tôi luôn thấy rằng làm theo cách đầu tiên nhanh hơn gần 10%, điều ngược lại với những gì bạn đã đề cập ở cuối : https://jsperf.com/immutable-js-list-of-maps-to-map-of-maps/1 – theopak

18

Một giải pháp có thể được sử dụng Bản đồ constructor từ liệt kê:

const ys = Immutable.Map(xs.map(v => [v.get('key'), v])); 
+1

Đây là câu trả lời đúng – astreltsov

0

Bạn có thể trao đổi một danh sách của Maps để một bản đồ của Lists bằng cách sử dụng kết hợp với reducemergeWith.

Thu nhỏ thông qua bộ sưu tập và hợp nhất từng mục mới bằng cách ghép các giá trị của nó lại với nhau.

collection.reduce((rr, ii) => rr.mergeWith((aa, bb) => List().concat(aa, bb), ii)) 
Các vấn đề liên quan