перетворити об'єкт в масив з lodash


165

Як я можу перетворити велике objectна arrayлодаш?

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 Так, оскільки документи мають такий чудовий огляд бібліотеки ... ні. Це лише вичерпний перелік функцій, і проходження кожної з них може виявити марну трату часу, якщо такої немає. Питання справедливе.
Епіроки

Відповіді:


264

Ви можете зробити

var arr = _.values(obj);

Документацію дивіться тут.


34
Що робити, якщо ви хотіли зберегти ключ як властивість? (у цьому прикладі, якщо idвластивості не існувало, і ви хотіли створити його на основі ключа кожного об'єкта.
Michael Liquori

8
Ви можете зробити щось подібне:var arr = _.values(_.mapKeys(obj, function(value, key) { value.id = key; return value; }));
Даніель Шмідт

1
@DanielSchmidt Я не впевнений, що я зробив не так, але цей зразок повернув лише 1 рядок для мене. :( Отже, що я зробив, це вручну підштовхнути returnзначення до такого масиву: const divisionsList = []; _.mapKeys(divisions, (value, key) => { divisionsList[key] = value; });я вдячний за будь-які коментарі чи пропозиції щодо вдосконалення цього підходу.
JohnnyQ

8
@JohnnyQ Я думаю, вам замість цього доведеться використовувати mapValues, наприкладconst toArrayWithKey = (obj, keyAs) => _.values(_.mapValues(obj, (value, key) => { value[keyAs] = key; return value; }));
orjan

1
@orjan Так, я насправді зрозумів це, просто забув оновити. Дякую тобі за це.
JohnnyQ

38
_.toArray(obj);

Виходи:

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

1
_.toArray () Відмінно працює @jivings
Syed Zain Ali

4
для отримання лише значень - це хороший варіант, але toArrayнемає можливості зберегти ключі, якщо потрібно.
Koushik Chatterjee

33

Сучасне рідне рішення, якщо когось цікавить:

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

або (не IE):

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

2
чому б не простоObject.keys(obj).map(key=>({key,value: obj[key]}))
Кушик Чаттерджі

1
Мені подобається, що це навіть не користувач лодаш, молодець!
ГолоднийПіпо

1
@Dominic Тепер ви змінили повну відповідь і взяли її з мого коментаря, навіть без згадки (ви це відредагували). Молодці 👏 😁😁
Koushik Chatterjee

1
@KoushikChatterjee додав це ще
Домінік

2
Чи було б це корисніше? const arr = Object.keys(obj).map(id => ({ id, ...obj[id] })); це призведе до повернення всього об'єкта у повернені дані ні? (використовуючи "id", оскільки початковий запитувач хотів зберегти свій ключ як id prop)
zabaat

20

Для мене це спрацювало:

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

Виходить

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

в

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

1
Мені потрібно було перетворити об’єкт у масив таким чином, щоб кожен ключ / значення вихідного об'єкта був {key: value} -об'єктом у масиві. _.toPairs (дані) приймає об’єкт {"a": "b", "c": "d", "e": "f"} і повертає його як масив масивів типу [["a": " b "], [" c ":" d "], [" e ":" f "]]. _.fromPairs робить навпаки, він бере масив з 2 елементами: ["a", "b"] і повертає його як об'єкт: {"a": "b"}. Використовуючи _.map, я повторював масив, якщо масиви, створені _.toPairs, перетворили його на масив об'єктів за допомогою _.fromPairs.
NoNine

1
Я радий, що прокрутився вниз, щоб побачити це. Ваше рішення працювало на мене! Дякую!
Уель

@NoNine Вам не потрібно застосовувати карту до масиву (масиву), ви можете безпосередньо застосувати її до вхідного об'єкта, і повернути кожну пару значень ключа, _.map(data, (v,k)=>({[k]: v}))детально дивіться мою відповідь. _.toPairsі тут _fromPairsє додатковим і непотрібним.
Koushik Chatterjee

Це не те, для чого питання призначене. тому що використовувати результат дуже важко, оскільки кожен запис містить ключ (якого ви не знаєте), і знову потрібно пройти певну логіку (наприклад, Object.keys або Object.values) для кожного окремого запису, щоб отримати значення кожний, якщо іграшка хоче зберегти ключі, то ви можете створити масив об’єктів, які залякують як[{key: 'someKey', val: 'The value'}, {....},...]
Koushik Chatterjee

13

Існує досить багато способів отримати результат, за яким ви прагнете. Розбиваємо їх на категорії:

Значення ES6 лише :

Основний метод для цього - Object.values . Але використання Object.keys і Array.map ви могли б також отримати до очікуваного результату:

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

Ключ та значення ES6 :

Використовуючи динамічні / обчислювані властивості map та ES6 та руйнуючи, ви можете зберегти ключ та повернути об’єкт з карти.

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

Цінності Лодаша :

Метод, розроблений для цього, _.valuesоднак є "ярлики", як _.mapі корисний метод, _.toArrayякий також повертає масив, що містить лише значення від об'єкта. Ви також можете _.mapхоч _.keysі отримати значення від об'єкта, використовуючи obj[key]позначення.

Примітка: _.mapпри передачі об'єкта використовується його baseMapобробник, який в основному forEachє властивостями об'єкта.

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

Ключ і значення Лодаша :

// 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), [])

Зауважте, що у наведених вище прикладах використовується ES6 (функції стрілок та динамічні властивості). Ви можете використовувати lodash _.fromPairsта інші методи для складання об'єкта, якщо ES6 є проблемою.


12

Якщо ви хочете, щоб ключ (id в цьому випадку) зберігався як властивість кожного елемента масиву, який ви можете зробити

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

2017 оновлення: Object.values , lodash значення і ToArray зробити це. І щоб зберегти карту ключів та оператор розповсюдження, грає добре:

// 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

Трансформація об'єкта в масив за допомогою простого 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);

Якщо ви хочете зберегти використання ключів Object.entriesі , Array#mapяк це:

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)

Ви також можете використовувати _.mapфункцію (і обох, lodashі з underscore) object, вона буде внутрішньо обробляти цей випадок, повторювати кожне значення та ключ зі своїм ітератом і, нарешті, повертати масив. Infact, ви можете використовувати його без будь-якого ітерату (просто _.map(obj)), якщо ви просто хочете масив значень. Хороша частина полягає в тому, що якщо вам потрібна якась трансформація між ними, ви можете зробити це за один раз.

Приклад:

Однак, якщо ви хочете перетворити свій об'єкт, ви можете це зробити, навіть якщо вам потрібно зберегти ключ, ви можете зробити це ( _.map(obj, (v, k) => {...}) з додатковим аргументом у, mapа потім використовувати його як хочете.

Однак є інші рішення для цього ванільного JS (як і будь-яке lodashрішення має бути чистою версією JS):

  • Object.keysа потім mapїх до значень
  • Object.values (у ES-2017)
  • Object.entriesа потім mapкожна пара ключ / значення (у ES-2017)
  • for...in циклічно і використовуйте кожну клавішу для отримання значень

І набагато більше. Але оскільки це питання призначене lodash(і якщо припустити, що хтось вже використовує його), то вам не потрібно багато думати про версію, підтримку методів та обробку помилок, якщо їх не знайдено.

Є й інші рішення для лодашів _.values( настільки зрозумілі для конкретних цілей), або отримання пар, а потім карта тощо. але у випадку, якщо вашому коду потрібна гнучкість, і ви зможете оновити його в майбутньому, оскільки вам потрібно keysтрохи зберегти або перетворити значення, тоді найкращим рішенням буде використання одиничного, _.mapяк адресованого у цій відповіді. Це також буде не таким складним, як на читабельність.


2
Приємно, дуже просто і найбільш стисло.
edencorbin

5

Об'єкт для масиву

З усіх відповідей я вважаю, що цей найкращий:

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

що перетворює:

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

до:

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

Масив до об’єкта

Для перетворення спини:

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

Для перетворення назад, зберігаючи ключ у значенні:

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

Дасть:

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

Для останнього прикладу ви також можете використовувати lodash _.keyBy(arr, 'key')або _.keyBy(arr, i => i.key).


3

Якщо ви хочете виконати спеціальне відображення (наприклад, оригінальний Array.prototype.map) об’єкта в масив, ви можете просто використовувати _.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' }, ... ];

Див. lodashДокумент домену _.forEach https://lodash.com/docs/#forEach

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.