chuyển đổi đối tượng thành mảng với lodash


165

Làm thế nào tôi có thể biến đổi lớn objectthành arrayvới lodash?

var obj = {
  22: {name:"John", id:22, friends:[5,31,55], works:{books:[], films:[],}
  12: {name:"Ivan", id:12, friends:[2,44,12], works:{books:[], films:[],}
}

// transform to 
var arr = [{name:"John", id:22...},{name:"Ivan", id:12...}]

@Mritunjay Có vì các tài liệu có một cái nhìn tổng quan tuyệt vời về thư viện ... không phải. Nó chỉ là một danh sách đầy đủ các chức năng và đi qua từng chức năng cũng có thể chứng minh sự lãng phí thời gian nếu không có chức năng. Câu hỏi là một công bằng.
Epirocks

Câu trả lời:


263

Bạn có thể làm

var arr = _.values(obj);

Đối với tài liệu xem tại đây.


34
Còn nếu bạn muốn bảo quản chìa khóa như một tài sản thì sao? (trong ví dụ này, nếu thuộc idtính không tồn tại và bạn muốn tạo nó dựa trên khóa của từng đối tượng.
Michael Liquori

8
Bạn có thể làm một cái gì đó như thế này:var arr = _.values(_.mapKeys(obj, function(value, key) { value.id = key; return value; }));
Daniel Schmidt

1
@DanielSchmidt Tôi không chắc mình đã làm gì sai nhưng mẫu đó chỉ trả lại 1 hàng cho tôi. :( Vì vậy, những gì tôi đã làm là tự đẩy returngiá trị lên một mảng như thế này: const divisionsList = []; _.mapKeys(divisions, (value, key) => { divisionsList[key] = value; });Tôi đánh giá cao bất kỳ nhận xét hoặc đề xuất nào để cải thiện phương pháp này.
JohnnyQ

8
@JohnnyQ Tôi nghĩ rằng bạn sẽ cần sử dụng mapValues ​​thay vào đóconst toArrayWithKey = (obj, keyAs) => _.values(_.mapValues(obj, (value, key) => { value[keyAs] = key; return value; }));
orjan

1
@orjan Có tôi thực sự đã tìm ra điều này, chỉ quên cập nhật. Cảm ơn vì điều đó.
JohnnyQ

38
_.toArray(obj);

Đầu ra là:

[
  {
    "name": "Ivan",
    "id": 12,
    "friends": [
      2,
      44,
      12
    ],
    "works": {
      "books": [],
      "films": []
    }
  },
  {
    "name": "John",
    "id": 22,
    "friends": [
      5,
      31,
      55
    ],
    "works": {
      "books": [],
      "films": []
    }
  }
]"

1
_.toArray () Hoạt động tốt @jivings
Syed Zain Ali

4
để chỉ nhận các giá trị, đây là một lựa chọn tốt, nhưng toArraykhông có cách nào để bảo vệ các khóa nếu được yêu cầu.
Koushik Chatterjee

33

Một giải pháp bản địa hiện đại nếu có ai quan tâm:

const arr = Object.keys(obj).map(key => ({ key, value: obj[key] }));

hoặc (không phải IE):

const arr = Object.entries(obj).map(([key, value]) => ({ key, value }));

2
tại sao không chỉObject.keys(obj).map(key=>({key,value: obj[key]}))
Koushik Chatterjee

1
Tôi thích rằng nó thậm chí không sử dụng lodash, làm tốt lắm thưa ông!
HungryPipo 16/03/18

1
@Dominic Bây giờ bạn đã thay đổi câu trả lời hoàn chỉnh của mình và lấy nó từ nhận xét của tôi, ngay cả khi không có đề cập (bạn đã chỉnh sửa nó). Làm tốt lắm 👏
Koushik Chatterjee

1
@KoushikChatterjee đã thêm lại
Dominic

2
Điều này sẽ hữu ích hơn? const arr = Object.keys(obj).map(id => ({ id, ...obj[id] })); Điều này sẽ mang lại toàn bộ đối tượng vào dữ liệu trả về không? (sử dụng 'id' vì người hỏi ban đầu muốn lưu trữ khóa của anh ấy dưới dạng id prop)
zabaat

20

Đối với tôi, điều này đã làm việc:

_.map(_.toPairs(data), d => _.fromPairs([d]));

Nó rẽ

{"a":"b", "c":"d", "e":"f"} 

vào

[{"a":"b"}, {"c":"d"}, {"e":"f"}]

1
Tôi cần phải chuyển đổi một đối tượng thành một mảng, theo cách mà mỗi khóa / giá trị của đối tượng ban đầu sẽ là một {key: value} -object trong mảng. _.toPairs (data) lấy đối tượng {"a": "b", "c": "d", "e": "f"} và trả về nó dưới dạng một mảng các mảng như [["a": " b "], [" c ":" d "], [" e ":" f "]]. _.fromPairs thì ngược lại, nó lấy một mảng có 2 phần tử: ["a", "b"] và trả về nó dưới dạng một đối tượng: {"a": "b"}. Sử dụng _.map Tôi đã lặp lại trên mảng nếu các mảng được tạo bởi _.toPairs để chuyển đổi nó thành một mảng các đối tượng với sự trợ giúp của _.fromPairs.
NoNine

1
Tôi vui vì tôi đã cuộn xuống để xem điều này. Giải pháp của bạn đã làm việc cho tôi! Cảm ơn!
Wale

@NoNine Bạn không cần áp dụng bản đồ trên một mảng (của mảng), bạn có thể trực tiếp áp dụng nó trên đối tượng đầu vào và trả về từng cặp giá trị khóa _.map(data, (v,k)=>({[k]: v}))xem chi tiết câu trả lời của tôi. _.toPairs_fromPairslà bổ sung và không cần thiết ở đây.
Koushik Chatterjee

Đây không phải là những gì câu hỏi có nghĩa là cho. bởi vì việc sử dụng kết quả này hơi khó khăn vì mỗi mục chứa một khóa (mà bạn không biết) và một lần nữa bạn cần trải qua một số logic (ví dụ: Object.keys hoặc Object.values) cho mỗi mục nhập riêng biệt để nhận giá trị của mỗi, nếu đồ chơi muốn bảo quản chìa khóa thì bạn có thể tạo ra một loạt các vật thể được sắp xếp theo kiểu như[{key: 'someKey', val: 'The value'}, {....},...]
Koushik Chatterjee

13

Có khá nhiều cách để có được kết quả mà bạn đang theo đuổi. Hãy phá vỡ chúng trong các danh mục:

Chỉ giá trị ES6 :

Phương thức chính cho điều này là Object.values . Nhưng bằng cách sử dụng Object.keysArray.map, bạn cũng có thể đạt được kết quả như mong đợi:

Object.values(obj)
Object.keys(obj).map(k => obj[k])

Khóa & giá trị ES6 :

Sử dụng các thuộc tính động / tính toán của bản đồ và ES6 và phá hủy, bạn có thể giữ lại khóa và trả về một đối tượng từ bản đồ.

Object.keys(obj).map(k => ({[k]: obj[k]}))
Object.entries(obj).map(([k,v]) => ({[k]:v}))

Chỉ có giá trị tạm thời :

Tuy nhiên, phương thức được thiết kế cho điều này là _.valuescó "phím tắt" như thế _.mapvà phương thức tiện ích _.toArraycũng sẽ trả về một mảng chỉ chứa các giá trị từ đối tượng. Bạn cũng có thể _.mapmặc dù _.keysvà nhận các giá trị từ đối tượng bằng cách sử dụng obj[key]ký hiệu.

Lưu ý: _.mapkhi được thông qua, một đối tượng sẽ sử dụng baseMaptrình xử lý của nó , về cơ bản là forEachtrên các thuộc tính của đối tượng.

_.values(obj)
_.map(obj)
_.toArray(obj)
_.map(_.keys(obj), k => obj[k])

Mã khóa & giá trị :

// Outputs an array with [[KEY, VALUE]]
_.entries(obj)
_.toPairs(obj)

// Outputs array with objects containing the keys and values
_.map(_.entries(obj), ([k,v]) => ({[k]:v}))
_.map(_.keys(obj), k => ({[k]: obj[k]}))
_.transform(obj, (r,c,k) => r.push({[k]:c}), [])
_.reduce(obj, (r,c,k) => (r.push({[k]:c}), r), [])

Lưu ý rằng trong các ví dụ trên, ES6 được sử dụng (các hàm mũi tên và thuộc tính động). Bạn có thể sử dụng lodash _.fromPairsvà các phương thức khác để soạn một đối tượng nếu ES6 là một vấn đề.


12

Nếu bạn muốn khóa (id trong trường hợp này) được bảo toàn như một thuộc tính của từng mục mảng, bạn có thể làm

const arr = _(obj) //wrap object so that you can chain lodash methods
            .mapValues((value, id)=>_.merge({}, value, {id})) //attach id to object
            .values() //get the values of the result
            .value() //unwrap array of objects

8

Cập nhật 2017: Object.values , giá trị lodash và toArray làm điều đó. Và để giữ bản đồ khóa và điều hành trải rộng chơi tốt:

// import { toArray, map } from 'lodash'
const map = _.map

const input = {
  key: {
    value: 'value'
  }
}

const output = map(input, (value, key) => ({
  key,
  ...value
}))

console.log(output)
// >> [{key: 'key', value: 'value'}])
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>


7

Chuyển đổi đối tượng thành mảng với JavaScript ( ECMAScript-2016) Object.values:

var obj = {
    22: {name:"John", id:22, friends:[5,31,55], works:{books:[], films:[]}},
    12: {name:"Ivan", id:12, friends:[2,44,12], works:{books:[], films:[]}}
}

var values = Object.values(obj)

console.log(values);

Nếu bạn cũng muốn giữ các phím sử dụng Object.entriesArray#mapnhư thế này:

var obj = {
    22: {name:"John", id:22, friends:[5,31,55], works:{books:[], films:[]}},
    12: {name:"Ivan", id:12, friends:[2,44,12], works:{books:[], films:[]}}
}

var values = Object.entries(obj).map(([k, v]) => ({[k]: v}))

console.log(values);


5

var arr = _.map(obj)

Bạn cũng có thể sử dụng _.maphàm (của cả hai lodashunderscore) object, nó sẽ xử lý bên trong trường hợp đó, lặp lại từng giá trị và khóa với iteratee của bạn và cuối cùng trả về một mảng. Nguyên vẹn, bạn có thể sử dụng nó mà không cần lặp lại (chỉ_.map(obj) ) nếu bạn chỉ muốn một mảng các giá trị. Phần tốt là, nếu bạn cần bất kỳ sự chuyển đổi nào ở giữa, bạn có thể thực hiện nó trong một lần.

Thí dụ:

Tuy nhiên, nếu bạn muốn chuyển đổi đối tượng của mình, bạn có thể làm như vậy, ngay cả khi bạn cần giữ khóa, bạn có thể làm điều đó ( _.map(obj, (v, k) => {...}) với đối số bổ sung mapvà sau đó sử dụng nó theo cách bạn muốn.

Tuy nhiên, có một giải pháp Vanilla JS khác cho điều này (vì mọi lodashgiải pháp nên có phiên bản thuần túy của nó) như:

  • Object.keysvà sau đó maphọ đến các giá trị
  • Object.values (trong ES-2017)
  • Object.entries và sau đó map từng cặp khóa / giá trị (trong ES-2017)
  • for...in lặp và sử dụng từng phím để xóa giá trị

Và nhiều hơn nữa. Nhưng vì câu hỏi này là dành cho lodash(và giả sử ai đó đã sử dụng nó) nên bạn không cần phải suy nghĩ nhiều về phiên bản, hỗ trợ phương pháp và xử lý lỗi nếu không tìm thấy.

Có các giải pháp lodash khác như _.values(dễ đọc hơn cho mục đích cụ thể), hoặc nhận các cặp và sau đó ánh xạ, v.v. nhưng trong trường hợp mã của bạn cần linh hoạt để bạn có thể cập nhật nó trong tương lai vì bạn cần bảo toàn keyshoặc biến đổi các giá trị một chút, thì giải pháp tốt nhất là sử dụng một đơn _.mapnhư là bổ sung trong câu trả lời này. Điều đó sẽ không khó khăn như vậy theo khả năng đọc cũng.


2
Đẹp, rất đơn giản và súc tích nhất.
edencorbin

5

Đối tượng với mảng

Trong tất cả các câu trả lời tôi nghĩ rằng đây là câu trả lời hay nhất:

let arr = Object.entries(obj).map(([key, val]) => ({ key, ...val }))

mà biến đổi:

{
  a: { p: 1, q: 2},
  b: { p: 3, q: 4}
}

đến:

[
  { key: 'a', p: 1, q: 2 }, 
  { key: 'b', p: 3, q: 4 }
]

Mảng đối tượng

Để chuyển đổi trở lại:

let obj = arr.reduce((obj, { key, ...val }) => { obj[key] = { ...val }; return obj; }, {})

Để chuyển đổi giữ lại khóa trong giá trị:

let obj = arr.reduce((obj, { key, ...val }) => { obj[key] = { key, ...val }; return obj; }, {})

Sẽ cho:

{
  a: { key: 'a', p: 1, q: 2 },
  b: { key: 'b', p: 3, q: 4 }
}

Đối với ví dụ cuối cùng, bạn cũng có thể sử dụng lodash _.keyBy(arr, 'key')hoặc _.keyBy(arr, i => i.key).


3

Nếu bạn muốn một số ánh xạ tùy chỉnh (như Array.prototype.map gốc) của Object thành một Array, bạn chỉ có thể sử dụng _.forEach:

let myObject = {
  key1: "value1",
  key2: "value2",
  // ...
};

let myNewArray = [];

_.forEach(myObject, (value, key) => {
  myNewArray.push({
    someNewKey: key,
    someNewValue: value.toUpperCase() // just an example of new value based on original value
  });
});

// myNewArray => [{ someNewKey: key1, someNewValue: 'VALUE1' }, ... ];

Xem lodashtài liệu của _.forEach https://lodash.com/docs/#forEach

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.