แปลงวัตถุเป็นอาร์เรย์ด้วย 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 ใช่เพราะเอกสารมีภาพรวมที่ยอดเยี่ยมของห้องสมุด ... ไม่ นี่เป็นเพียงรายการฟังก์ชั่นที่ครบถ้วนสมบูรณ์และการผ่านแต่ละฟังก์ชั่นสามารถพิสูจน์ได้ว่าเป็นการเสียเวลาหากไม่มี คำถามนี้เป็นคำถามที่ยุติธรรม
Epirocks

คำตอบ:


264

คุณทำได้

var arr = _.values(obj);

สำหรับเอกสารดูที่นี่


34
ถ้าคุณต้องการเก็บรักษาคีย์เป็นคุณสมบัติหรือไม่ (ในตัวอย่างนี้ถ้าไม่มีidคุณสมบัติและคุณต้องการสร้างขึ้นโดยใช้คีย์ของแต่ละวัตถุ
Michael Liquori

8
คุณสามารถทำสิ่งนี้:var arr = _.values(_.mapKeys(obj, function(value, key) { value.id = key; return value; }));
Daniel Schmidt

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]}))
Koushik Chatterjee

1
ฉันชอบที่มันไม่ได้แม้แต่ผู้ใช้ lodash ทำได้ดีมาก!
HungryPipo

1
@Dominic ตอนนี้คุณเปลี่ยนคำตอบทั้งหมดและนำมาจากความคิดเห็นของฉันแม้จะไม่มีการเอ่ยถึง (คุณแก้ไขออก) ทำได้ดีมาก😁😁😁😁
Koushik Chatterjee

1
@KoushikChatterjee เพิ่มกลับแล้ว
Dominic

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
ฉันต้องการเปลี่ยนวัตถุให้เป็น Array ในลักษณะที่แต่ละคีย์ / ค่าของวัตถุดั้งเดิมจะเป็น {key: value} -object ในอาร์เรย์ _.toPairs (data) รับวัตถุ {"a": "b", "c": "d", "e": "f"} และส่งคืนเป็นอาร์เรย์ของอาร์เรย์เช่น [["a": " b "], [" c ":" d "], [" e ":" f "]] _.fromPairs ทำสิ่งที่ตรงกันข้ามมันต้องใช้ Array ที่มี 2 องค์ประกอบ: ["a", "b"] และส่งคืนเป็นวัตถุ: {"a": "b"} การใช้ _.map ฉันทำซ้ำผ่านอาร์เรย์ถ้าอาร์เรย์ที่สร้างโดย _.toPairs เพื่อแปลงเป็นอาร์เรย์ของวัตถุด้วยความช่วยเหลือของ _.fromPairs
NoNine

1
ฉันดีใจที่ฉันเลื่อนลงเพื่อดูสิ่งนี้ ทางออกของคุณใช้ได้สำหรับฉัน! ขอบคุณ!
Wale

@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 :

การใช้แผนที่และคุณสมบัติแบบไดนามิก / คำนวณของ ES6 และการทำลายล้างคุณสามารถเก็บรหัสและส่งคืนวัตถุจากแผนที่

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

ค่า Lodash เท่านั้น :

วิธีที่ออกแบบมาสำหรับสิ่งนี้คือ_.valuesอย่างไรก็ตามมี "ทางลัด" ที่ชอบ_.mapและวิธีการยูทิลิตี้_.toArrayซึ่งจะส่งกลับอาร์เรย์ที่มีเพียงค่าจากวัตถุ คุณยังสามารถ_.mapแม้ว่า_.keysและรับค่าจากวัตถุโดยใช้obj[key]สัญกรณ์

หมายเหตุ: _.mapเมื่อผ่านวัตถุจะใช้baseMapตัวจัดการของมันซึ่งเป็นพื้นforEachในคุณสมบัติของวัตถุ

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

Lodash Key & Value :

// 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เช่นกันมันจะจัดการภายในกรณีนั้นซ้ำผ่านแต่ละค่าและคีย์ด้วย iterate ของคุณและในที่สุดก็กลับอาร์เรย์ โดยปกติแล้วคุณสามารถใช้มันได้โดยไม่ต้องมีการวนซ้ำ (เพียง_.map(obj)) ถ้าคุณต้องการอาร์เรย์ของค่า ส่วนที่ดีคือถ้าคุณต้องการการเปลี่ยนแปลงใด ๆ ในระหว่างนั้นคุณสามารถทำได้ในครั้งเดียว

ตัวอย่าง:

อย่างไรก็ตามหากคุณต้องการแปลงวัตถุของคุณคุณสามารถทำได้แม้ว่าคุณจะต้องรักษารหัสไว้คุณสามารถทำเช่นนั้น ( _.map(obj, (v, k) => {...}) โดยมีอาร์กิวเมนต์เพิ่มเติมmapจากนั้นจึงใช้ตามที่คุณต้องการ

อย่างไรก็ตามมีวิธีการแก้ปัญหา Vanilla JS อื่น ๆ (เช่นเดียวกับlodashวิธีแก้ปัญหาทุกอย่างควรมีรุ่น JS บริสุทธิ์) เช่น:

  • Object.keysจากนั้นmapให้เป็นค่า
  • Object.values (ใน ES-2017)
  • Object.entriesแล้วmapแต่ละคู่คีย์ / ค่า (ใน ES-2017)
  • for...in วนและใช้แต่ละปุ่มสำหรับค่า feting

และอีกมากมาย แต่เนื่องจากคำถามนี้มีไว้สำหรับlodash(และสมมติว่ามีคนใช้อยู่แล้ว) คุณไม่จำเป็นต้องคิดมากเกี่ยวกับเวอร์ชันการสนับสนุนวิธีการและการจัดการข้อผิดพลาดหากไม่พบ

มีวิธีแก้ปัญหาบ้านพักอื่น ๆ เช่น_.values(อ่านได้ง่ายขึ้นสำหรับเฉพาะเจาะจง) หรือรับคู่แล้วแผนที่และอื่น ๆ แต่ในกรณีที่โค้ดของคุณต้องการความยืดหยุ่นที่คุณสามารถอัปเดตได้ในอนาคตเมื่อคุณต้องการรักษาkeysหรือเปลี่ยนแปลงค่าเล็กน้อยดังนั้นทางออกที่ดีที่สุดคือการใช้สิ่ง_.mapที่เพิ่มเข้าไปในคำตอบนี้ ที่จะไม่ยากที่ตามการอ่านด้วย


2
นีซเรียบง่ายและรัดกุมที่สุด
edencorbin

5

Object to Array

จากคำตอบทั้งหมดฉันคิดว่าอันนี้ดีที่สุด:

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 }
]

Array to Object

ในการเปลี่ยนกลับ:

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) ดั้งเดิมของ Object ไปยัง Array คุณสามารถใช้_.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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.