Bản đồ trên các khóa bảo quản đối tượng


129

Các mapchức năng trong underscore.js, nếu gọi với một đối tượng javascript, trả về một mảng các giá trị ánh xạ từ các giá trị của đối tượng.

_.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; });
=> [3, 6, 9]

Có cách nào để làm cho nó bảo quản các phím? tức là tôi muốn một hàm trả về

{one: 3, two: 6, three: 9}

Nếu bạn, giống như tôi, đến đây để tìm kiếm một chức năng giống như 'mapValues' thay đổi đối tượng thực tế thay vì trả lại một đối tượng mới, hãy kiểm tra giải pháp đơn giản này: stackoverflow.com/questions/30894044/
trộm

Câu trả lời:


228

Với gạch dưới

Underscore cung cấp một chức năng _.mapObjectđể ánh xạ các giá trị và bảo tồn các khóa.

_.mapObject({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });

// => { one: 3, two: 6, three: 9 }

DEMO


Với nhà nghỉ

Lodash cung cấp một chức năng _.mapValuesđể ánh xạ các giá trị và bảo tồn các khóa.

_.mapValues({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });

// => { one: 3, two: 6, three: 9 }

DEMO


Đã có những nỗ lực để đưa hàm _.mapValues ​​vào dấu gạch dưới: Vấn đề có liên quan , Yêu cầu kéo cho _.mapValues . Tôi hy vọng điều này sẽ đi qua :)
raffomania

đối với tôi có vẻ như bạn đang biến ĐỐI TƯỢNG thành một đối tượng, hoặc tôi mất trí?
JSH

@jsh Trong trường hợp này, _.map()đang trả về [['one', 3], ['two', 6], ['three', 9]], đó là một mảng các mảng và _.object()đang biến nó trở lại thành một đối tượng.
Jezen Thomas

56

Tôi quản lý để tìm các chức năng cần thiết trong lodash, một thư viện tiện ích tương tự như gạch dưới.

http://lodash.com/docs#mapValues

_.mapValues(object, [callback=identity], [thisArg])

Tạo một đối tượng có cùng khóa với đối tượng và các giá trị được tạo bằng cách chạy từng thuộc tính vô số riêng của đối tượng thông qua hàm gọi lại. Cuộc gọi lại được ràng buộc với thisArg và được gọi với ba đối số; (giá trị, khóa, đối tượng).


19

var mapped = _.reduce({ one: 1, two: 2, three: 3 }, function(obj, val, key) {
    obj[key] = val*3;
    return obj;
}, {});

console.log(mapped);
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>


13

Tôi biết điều này đã cũ, nhưng bây giờ Underscore có một bản đồ mới cho các đối tượng:

_.mapObject(object, iteratee, [context]) 

Tất nhiên bạn có thể xây dựng một bản đồ linh hoạt cho cả mảng và đối tượng

_.fmap = function(arrayOrObject, fn, context){
    if(this.isArray(arrayOrObject))
      return _.map(arrayOrObject, fn, context);
    else
      return _.mapObject(arrayOrObject, fn, context);
}

5
Lưu ý đối với người dùng lodash: jdalton đã quyết định phá vỡ tính tương thích với underscore.js về thay đổi này. lodash sẽ không hỗ trợ mapObject; mapValuesthay vào đó hãy nhìn vào phương pháp của lodash .
Mark Amery

13

Làm thế nào về phiên bản này trong JS đơn giản ( ES6 / ES2015 )?

let newObj = Object.assign(...Object.keys(obj).map(k => ({[k]: obj[k] * 3})));

jsbin

Nếu bạn muốn ánh xạ qua một đối tượng đệ quy (ánh xạ lồng nhau obj), nó có thể được thực hiện như thế này:

const mapObjRecursive = (obj) => {
  Object.keys(obj).forEach(key => {
    if (typeof obj[key] === 'object') obj[key] = mapObjRecursive(obj[key]);
    else obj[key] = obj[key] * 3;
  });
  return obj;
};

jsbin

ES7 / ES2016, bạn có thể sử dụng Object.entriesthay vì Object.keysnhư thế này:

let newObj = Object.assign(...Object.entries(obj).map([k, v] => ({[k]: v * 3})));

5

Tôi biết đó là một thời gian dài, nhưng vẫn còn giải pháp rõ ràng nhất thông qua nếp gấp (còn gọi là giảm js), vì sự hoàn chỉnh tôi sẽ để nó ở đây:

function mapO(f, o) {
  return Object.keys(o).reduce((acc, key) => {
    acc[key] = f(o[key])
    return acc
  }, {})
}

Tôi ổn với việc sử dụng thư viện Lodash nhưng các lập trình viên đang sử dụng các loại thư viện này và không biết làm thế nào những điều này có thể đạt được trong vanilla JS. Vì vậy, tôi đánh giá cao câu trả lời của bạn!
cyonder

3

_.map trả về một Mảng chứ không phải Object.

Nếu bạn muốn một đối tượng, bạn nên sử dụng một chức năng khác, như each; nếu bạn thực sự muốn sử dụng bản đồ, bạn có thể làm một cái gì đó như thế này:

Object.keys(object).map(function(value, index) {
   object[value] *= 3;
})

nhưng điều đó thật khó hiểu, khi nhìn thấy mapngười ta sẽ mong đợi có một mảng là kết quả và sau đó tạo ra một cái gì đó với nó.


Tôi có cảm giác đọc các tài liệu rằng sẽ không tự nhiên khi thử điều này trong underscore.js. Tôi nghĩ trường hợp sử dụng của tôi khá tự nhiên, tại sao họ không hỗ trợ?
xuanji

Một lý do có thể maplà được sử dụng để thay đổi đầu vào tạo ra một mảng làm đầu ra, bạn có thể soạn _.object_.maplà @GG. đã viết, nhưng đó là một vấn đề của hương vị tại thời điểm này.
Alberto Zaccagni

3

Tôi nghĩ rằng bạn muốn có một hàm mapValues (để ánh xạ một hàm qua các giá trị của một đối tượng), điều này đủ dễ để tự thực hiện:

mapValues = function(obj, f) {
  var k, result, v;
  result = {};
  for (k in obj) {
    v = obj[k];
    result[k] = f(v);
  }
  return result;
};

2
const mapObject = (obj = {}, mapper) =>
  Object.entries(obj).reduce(
    (acc, [key, val]) => ({ ...acc, [key]: mapper(val) }),
    {},
  );

Tôi đã định thêm câu trả lời này cho mình. Vui mừng tôi đã cuộn!
Bill Criswell

0

Một bản sửa lỗi kết hợp cho lỗi bản đồ gạch dưới : P

_.mixin({ 
    mapobj : function( obj, iteratee, context ) {
        if (obj == null) return [];
        iteratee = _.iteratee(iteratee, context);
        var keys = obj.length !== +obj.length && _.keys(obj),
            length = (keys || obj).length,
            results = {},
            currentKey;
        for (var index = 0; index < length; index++) {
          currentKey = keys ? keys[index] : index;
          results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
        }
        if ( _.isObject( obj ) ) {
            return _.object( results ) ;
        } 
        return results;
    }
}); 

Một cách giải quyết đơn giản là giữ đúng khóa và trả về làm đối tượng Nó vẫn được sử dụng giống như cách tôi làm khách, bạn có thể sử dụng chức năng này để ghi đè hàm _.map lỗi

hoặc đơn giản là tôi đã sử dụng nó như một hỗn hợp

_.mapobj ( options , function( val, key, list ) 

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.