2012-06-11 26 views
9

Không có hàm Javascript hoặc Coffeescript phổ biến/tiêu chuẩn nào chuyển đổi các giá trị của một đối tượng/bản đồ/băm?Bất kỳ hàm bản đồ nào của Javascript hoặc Coffeescript có thể chuyển đổi các giá trị * đối tượng *?

jQuery has $.map nhưng chỉ tạo ra Array s.
Underscore has _.map nhưng cũng chỉ tạo ra Array s.

Để rõ ràng, một chức năng như thế này là những gì tôi đang tìm kiếm. (Ví dụ này được viết bằng Coffeescript không Javascript.)

# Transforms the values in a map. (Doesn't modify `obj` — returns a new map.) 
# Example usage: 
# mapObjVals({ a: 'aa', b: 'bb'}, (key, value) -> value + '_!') 
# --> { a: 'aa_!', b: 'bb_!' } 
mapObjVals = (obj, f) -> 
    obj2 = {} 
    for k, v of obj 
    obj2[k] = f k, v 
    obj2 
+1

Bạn dường như đã trả lời câu hỏi của riêng mình :) Chỉ cần đảm bảo bạn sử dụng 'cho riêng k, v của obj' để tránh bị bit bởi phần mở rộng mẫu thử nghiệm. Tôi sẽ sử dụng vòng lặp 'for' trực tiếp thay vì một hàm trợ giúp, vì đây là một ocurrence hiếm. –

Trả lời

6

Nếu bạn muốn ánh xạ một đối tượng đến một đối tượng, bạn cần phải sử dụng một fold (thuật ngữ truyền thống chức năng) hoặc reduce (tên hiện đại phổ biến, được sử dụng bởi dấu gạch dưới), tạo giá trị mới từ bộ sưu tập:

_.reduce(obj, function(newObj, thisValue, thisKey) { 
     // modify newObj based on thisKey/thisValue 
     return newObj; 
     }, {}) 

Hàm được chuyển làm đối số thứ hai được gọi một lần cho mỗi cặp khóa/giá trị. Nó được truyền vào đối tượng đang được xây dựng làm đối số đầu tiên của nó, tiếp theo là giá trị hiện tại, tiếp theo là khóa liên quan. Tùy thuộc vào hàm để sửa đổi đối tượng và trả về giá trị mới của nó.

Đối số thứ ba cho _.reduce là giá trị ban đầu của đối tượng mới, được chuyển vào bằng cặp khóa/giá trị đầu tiên; trong trường hợp này, nó là một đối tượng rỗng/bản đồ/băm {}.

Giảm/gấp/tiêm thường được sử dụng để tính tổng giá trị. Về cơ bản, bất cứ lúc nào bạn muốn xây dựng một giá trị đơn mới từ một bộ sưu tập. map thực sự chỉ là trường hợp đặc biệt của reduce trong đó giá trị bị cáo buộc giảm thực sự là một bộ sưu tập có cùng kích thước với bản gốc.

Đối với CoffeeScript, AFAIK, danh sách hiểu luôn luôn trả về danh sách, ngay cả khi lặp qua đối tượng. Vì vậy, bạn có thể muốn xem xét the CoffeeScript version of Underscore.

+0

Cảm ơn! Tôi lấy ví dụ '+ '_!'' Của mình làm việc với '_.reduce' như sau:' _ ({a: 'aa', b: 'bb'}). ((Bản ghi nhớ, giá trị, chỉ mục) -> memo [index] = value + '_!'; memo), {} ' – KajMagnus

+1

" Đáng tiếc ", với' _.reduce', tôi phải 1) trả về 'memo' từ bên trong trình lặp, và 2) vượt qua' { } 'to' reduce'. Vì vậy, nó có phần chi tiết hơn. Thực ra tôi thấy hàm ví dụ của mình dễ hiểu hơn - khi tôi đọc 'mapObjVals ({a: 'aa', b: 'bb'}, (khóa, giá trị) -> giá trị + '_!')' Tôi hiểu khá nhanh những gì đang được thực hiện. – KajMagnus

+0

Có, giảm là chi tiết hơn vì nó tổng quát hơn; bản đồ có thể dễ dàng được thực hiện về mặt giảm. Cho dù bạn cảm thấy cần phải viết một chức năng trợ giúp để che giấu sự rườm rà đó là tùy theo sở thích cá nhân .. –

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