przekształcić obiekt w tablicę z lodash

165

W jaki sposób można przekształcić wielkim objectaby arrayz 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...}]
siavolt
źródło
@Mritunjay Tak, ponieważ dokumenty mają świetny przegląd biblioteki ... nie. To tylko wyczerpująca lista funkcji, a przeglądanie każdej z nich może okazać się stratą czasu, jeśli takiej nie ma. Pytanie jest uczciwe.
Epirocks

Odpowiedzi:

264

Możesz to zrobić

var arr = _.values(obj);

Dokumentację można znaleźć tutaj.

Daniel Schmidt
źródło
34
A co by było, gdybyś chciał zachować klucz jako własność? (w tym przykładzie, jeśli idnieruchomość nie istnieje i chcesz ją utworzyć na podstawie klucza każdego obiektu.
Michael Liquori
8
Możesz zrobić coś takiego:var arr = _.values(_.mapKeys(obj, function(value, key) { value.id = key; return value; }));
Daniel Schmidt
1
@DanielSchmidt Nie jestem pewien, co zrobiłem źle, ale ta próbka zwróciła dla mnie tylko 1 wiersz. :( Więc to, co zrobiłem, to ręcznie przekazałem returnwartość do tablicy takiej jak ta: const divisionsList = []; _.mapKeys(divisions, (value, key) => { divisionsList[key] = value; });Byłbym wdzięczny za wszelkie komentarze lub sugestie dotyczące ulepszenia tego podejścia.
JohnnyQ
8
@JohnnyQ Myślę, że będziesz musiał zamiast tego użyć mapValues, np.const toArrayWithKey = (obj, keyAs) => _.values(_.mapValues(obj, (value, key) => { value[keyAs] = key; return value; }));
orjan
1
@orjan Tak, właściwie to rozgryzłem, po prostu zapomniałem zaktualizować. Dziękuję za to.
JohnnyQ,
38
_.toArray(obj);

Wyniki jako:

[
  {
    "name": "Ivan",
    "id": 12,
    "friends": [
      2,
      44,
      12
    ],
    "works": {
      "books": [],
      "films": []
    }
  },
  {
    "name": "John",
    "id": 22,
    "friends": [
      5,
      31,
      55
    ],
    "works": {
      "books": [],
      "films": []
    }
  }
]"
Jivings
źródło
1
_.toArray () Działa dobrze @jivings
Syed Zain Ali
4
do uzyskiwania tylko wartości jest to dobra opcja, ale w toArrayrazie potrzeby nie ma sposobu, aby zachować klucze.
Koushik Chatterjee
33

Nowoczesne natywne rozwiązanie, jeśli ktoś jest zainteresowany:

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

lub (nie IE):

const arr = Object.entries(obj).map(([key, value]) => ({ key, value }));
Dominic
źródło
2
dlaczego nie tylkoObject.keys(obj).map(key=>({key,value: obj[key]}))
Koushik Chatterjee
1
Podoba mi się, że nawet nie jest to użytkownik lodash, dobra robota!
HungryPipo
1
@Dominic Teraz zmieniłeś swoją pełną odpowiedź i wziąłeś ją z mojego komentarza, nawet bez wzmianki (zredagowałeś to). Dobra robota 👏 😁😁
Koushik Chatterjee
1
@KoushikChatterjee dodał to z powrotem
Dominic
2
Czy to byłoby bardziej pomocne? const arr = Object.keys(obj).map(id => ({ id, ...obj[id] })); spowodowałoby to przeniesienie całego obiektu do zwróconych danych nie? (używając 'id', ponieważ pierwotny pytający chciał przechowywać swój klucz jako rekwizyt id)
zabaat
20

U mnie to zadziałało:

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

Skręca, zakręca

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

w

[{"a":"b"}, {"c":"d"}, {"e":"f"}]
NoNine
źródło
1
Musiałem przekształcić obiekt w tablicę w taki sposób, aby każdy klucz / wartość oryginalnego obiektu był {klucz: wartość} -obiektem w tablicy. _.toPairs (data) pobiera obiekt {"a": "b", "c": "d", "e": "f"} i zwraca go jako tablicę tablic, np. [["a": " b "], [" c ":" d "], [" e ":" f "]]. _.fromPairs robi odwrotnie, pobiera Array z 2 elementami: ["a", "b"] i zwraca ją jako obiekt: {"a": "b"}. Używając _.map, iterowałem po tablicy, jeśli tablice utworzone przez _.toPairs, aby przekształcić ją w tablicę obiektów za pomocą _.fromPairs.
NoNine
1
Cieszę się, że przewinęłam stronę, żeby to zobaczyć. Twoje rozwiązanie zadziałało dla mnie! Dzięki!
Wale
@NoNine Nie musisz stosować mapy na tablicy (tablicy), możesz ją bezpośrednio zastosować na obiekcie wejściowym i zwrócić każdą parę klucz-wartość, _.map(data, (v,k)=>({[k]: v}))zobacz moją odpowiedź po szczegóły. _.toPairsi _fromPairsjest tutaj dodatkowy i niepotrzebny.
Koushik Chatterjee
Nie o to chodzi w tym pytaniu. ponieważ użycie wyniku jest nieco trudne, ponieważ każdy wpis zawiera klucz (którego nie znasz) i ponownie musisz przejść przez jakąś logikę (np. Object.keys lub Object.values) dla każdego oddzielnego wpisu, aby uzyskać wartość każdy, jeśli zabawka chce zachować klucze, możesz stworzyć szereg obiektów, które ułożone są jak[{key: 'someKey', val: 'The value'}, {....},...]
Koushik Chatterjee
13

Istnieje kilka sposobów na osiągnięcie pożądanego rezultatu. Podzielmy je na kategorie:

Tylko wartości ES6 :

Główną metodą jest Object.values . Ale używając Object.keys i Array.map , równie dobrze możesz uzyskać oczekiwany wynik:

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

Klucz i wartość ES6 :

Używając map i ES6 dynamicznych / obliczonych właściwości i destrukturyzacji , możesz zachować klucz i zwrócić obiekt z mapy.

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

Tylko wartości Lodash :

Metoda zaprojektowana do tego jest _.valuesjednak „skróty”, jak _.mapi metoda narzędziowa, _.toArrayktóra również zwraca tablicę zawierającą tylko wartości z obiektu. Możesz również skorzystać _.mapz _.keysi pobrać wartości z obiektu przy użyciu obj[key]notacji.

Uwaga: _.mapprzekazany obiekt użyłby swojego programu baseMapobsługi, który jest w zasadzie forEachna właściwościach obiektu.

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

Klucz i wartość Lodash :

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

Należy zauważyć, że w powyższych przykładach używany jest ES6 (funkcje strzałkowe i właściwości dynamiczne). Możesz użyć lodash _.fromPairsi innych metod do komponowania obiektu, jeśli problemem jest ES6.

Akrion
źródło
12

Jeśli chcesz, aby klucz (w tym przypadku id) został zachowany jako właściwość każdego elementu tablicy, możesz to zrobić

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
Sello Mkantjwa
źródło
8

Aktualizacja 2017: Object.values , lodash values i toArray . Aby zachować mapę klawiszy i rozłożyć operator, graj dobrze:

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

Vladimir Chervanev
źródło
7

Przekształcanie obiektu w tablicę za pomocą zwykłego kodu 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);

Jeśli chcesz również zachować klucze, użyj Object.entriesi w Array#mapten sposób:

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);

Czarnobrody
źródło
5

var arr = _.map(obj)

Możesz również użyć _.mapfunkcji (zarówno lodashi underscore) z, objectjak również, będzie ona wewnętrznie obsługiwać ten przypadek, iterować po każdej wartości i kluczu za pomocą iteracji, a na koniec zwróci tablicę. W rzeczywistości możesz go używać bez iteracji (po prostu _.map(obj)), jeśli potrzebujesz tylko tablicy wartości. Zaletą jest to, że jeśli potrzebujesz jakiejkolwiek transformacji pomiędzy, możesz to zrobić za jednym razem.

Przykład:

Jeśli jednak chcesz przekształcić swój obiekt, możesz to zrobić, nawet jeśli chcesz zachować klucz, możesz to zrobić ( _.map(obj, (v, k) => {...}) z dodatkowym argumentem in, mapa następnie użyć go tak, jak chcesz.

Istnieją jednak inne rozwiązania Vanilla JS do tego (jak każde lodashrozwiązanie powinno mieć czystą wersję JS), takie jak:

  • Object.keysa potem mapje wartościom
  • Object.values (w ES-2017)
  • Object.entriesa następnie mapkażda para klucz / wartość (w ES-2017)
  • for...in pętli i użyj każdego klucza do pobierania wartości

I dużo więcej. Ale ponieważ to pytanie jest dla lodash(i zakładając, że ktoś już go używa), nie musisz dużo myśleć o wersji, obsłudze metod i obsłudze błędów, jeśli te nie zostaną znalezione.

Istnieją inne rozwiązania lodash, takie jak _.values(bardziej czytelne dla określonego celu) lub pobieranie par, a następnie mapowanie i tak dalej. ale w przypadku, gdy kod wymaga elastyczności, aby można go było zaktualizować w przyszłości, ponieważ trzeba keysnieco zachować lub przekształcić wartości, najlepszym rozwiązaniem jest użycie pojedynczego _.mapadresu jako adresu w tej odpowiedzi. Nie będzie to takie trudne, jak na czytelność.

Koushik Chatterjee
źródło
2
Ładnie, bardzo prosto i zwięźle.
edencorbin
5

Obiekt do tablicy

Ze wszystkich odpowiedzi myślę, że ta jest najlepsza:

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

to zmienia:

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

do:

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

Array to Object

Aby przekształcić z powrotem:

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

Aby przekształcić z powrotem, zachowując klucz w wartości:

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

Da:

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

W ostatnim przykładzie możesz również użyć lodash _.keyBy(arr, 'key')lub _.keyBy(arr, i => i.key).

orad
źródło
3

Jeśli chcesz trochę niestandardowego mapowania (na przykład oryginalnego Array.prototype.map) obiektu na tablicę, możesz po prostu użyć _.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' }, ... ];

Zobacz lodashdokument _.forEach https://lodash.com/docs/#forEach

Gil Epshtain
źródło