เปลี่ยนอาเรย์ใน javascript เป็นวัตถุที่ง่ายกว่า


17

ฉันมี JSON ง่าย ๆ ที่มีอาร์เรย์ที่มีวัตถุอื่น ๆ เพิ่มเติมเช่นนี้

languagePack:
[
  {
    'key': 'Username',
    'value': 'Benutzername',
    'group': 'default'
  },
  {
    'key': 'Password',
    'value': 'Passwort',
    'group': 'default'
  }
]

แต่สิ่งที่ฉันต้องการจริงๆคือวัตถุเช่นนี้:

languagePack: 
{
    'Username': 'Benutzername',
    'Password': 'Passwort'
}

ดังนั้นฉันต้องการลดอาร์เรย์ให้เป็นคู่คีย์ - ค่า - แบบง่ายๆที่อยู่ในอาร์เรย์หรือแม้แต่วัตถุ (คีย์นั้นไม่ซ้ำกัน) ใครบ้างมีความคิดวิธีการลดสิ่งนี้ด้วยฟังก์ชั่นอาเรย์แถวบางส่วน ฉันสร้างสิ่งที่เหมือนกันสำหรับแต่ละสิ่งและสร้างวัตถุ "ด้วยมือ" สำหรับทรัพย์สิน แต่ฉันจำได้ว่ามีบางสิ่งที่ยอดเยี่ยมสำหรับอาร์เรย์เช่น 'ลด' ผู้ดำเนินการแพร่กระจาย (... ) แผนที่ทุก ๆ บางอย่าง ฯลฯ

ฉันลองกับสิ่งที่ชอบ:

var temp = this.languagePack.map(([key, value]) => ({key,value}))
console.log(temp)

แต่นั่นทำให้ฉันเกิดข้อผิดพลาด TypeError: Invalid attempt to destructure non-iterable instance

แก้ไข: ทั้งสามคำตอบทำงานได้อย่างสมบูรณ์แบบ ขอบคุณ



groupจะถูกละเว้น?
Bergi

ใช่กลุ่มสามารถถูกเพิกเฉยมันเป็นความคิดของเพื่อนร่วมงานของฉันที่จะใช้คีย์เดียวกันในหน้าจอต่าง ๆ ที่มีการแปลต่างกัน แต่ฉันไม่พบการใช้งานจริงสำหรับมัน แต่ที่เป็นคำถามสำหรับมากภายหลัง :) อีก
Marcel Grüger

คำตอบ:


11

โดยทั่วไปคุณต้องใช้forEachแทนmapฟังก์ชั่นจากนั้นคุณสามารถสร้างวัตถุนั้นกับคีย์ใด ๆ คู่ค่าที่คุณต้องการเก็บไว้

ลองสิ่งนี้มันจะแก้ปัญหาของคุณ

var temp = {};

this.languagePack.forEach(({key,value}) => {
    temp[key] = value
})

console.log(temp)

หมายเหตุ: ที่นี่เราไม่ได้ใช้mapเพราะเราต้องการส่งคืนวัตถุไม่ใช่อาร์เรย์ดังนั้นเราสามารถใช้reduceฟังก์ชั่นที่นี่เพื่อทำเช่นนั้น แต่ฉันคิดว่ามันจะง่ายและเข้าใจได้ง่ายในสิ่งที่เราต้องการและเรากำลังทำอะไรอยู่ที่นี่


10

คุณสามารถใช้reduceฟังก์ชั่นจาวาสคริปต์เพื่อสร้างวัตถุที่ว่างเปล่าและใส่แต่ละคีย์และค่าในนั้น

const data = [
  {
    'key': 'Username',
    'value': 'Benutzername',
    'group': 'default'
  },
  {
    'key': 'Password',
    'value': 'Passwort',
    'group': 'default'
  }
];

const newData = data.reduce((acc, row) => {
  acc[row.key] = row.value;
  return acc;
}, {});

console.log(newData);

แก้ไข: ดีแนะนำของดอนนี่ Verduijn คุณสามารถใช้การทำลายล้าง es6 เพื่อเขียนฟังก์ชันให้สั้นลง

const newData = data.reduce((acc, { key, value }) => ({ ...acc, [key]: value }), {});

3
หากคุณต้องการใช้ไวยากรณ์ ES6 คุณยังสามารถใช้ฟังก์ชั่นการลดด้วยวิธีนี้ได้(acc, { key, value }) => ({ ...acc, [key]: value })
Donny Verduijn

1
นอกจากนี้คุณสามารถใช้โอเปอเรเตอร์คอมม่าเพื่อหลีกเลี่ยงการส่งคืน:const newData = data.reduce((acc, row) => (acc[row.key] = row.value, acc), {});
ElChiniNet

4
เช่นเดียวกับความอยากรู้อยากเห็น ก่อนหน้านี้ฉันกำลังทดสอบประสิทธิภาพของตัวดำเนินการสเปรดเพื่อทำลายวัตถุและแม้ว่ามันจะเป็นความจริงที่บางครั้งมันปรับปรุงความสามารถในการอ่านรหัสได้ แต่ก็มีค่าใช้จ่ายสูง: measurethat.net/Benchmarks/Show/6194/5/ …
ElChiniNet

@ElChiniNet กรณีทดสอบที่คุณเชื่อมโยงนั้นเกี่ยวกับการแพร่กระจายของอาร์เรย์ไม่ใช่การแพร่กระจายวัตถุ (แต่ใช่แล้วการแพร่กระจายไปยังวัตถุใหม่ซ้ำ ๆ นั้นช้ากว่าการกลายพันธุ์วัตถุหนึ่ง ๆ )
15909

1
@Bergi ที่นี่คุณมีการเปรียบเทียบรหัสเฉพาะนี้: measurethat.net/Benchmarks/Show/6318/0//
ElChiniNet

6

ใช้กับArray#mapมันสร้างคีย์และค่าเป็นวัตถุและObject.assignค่าอาร์เรย์แอบแฝงไปยังวัตถุ

const languagePack = [ { 'key': 'Username', 'value': 'Benutzername', 'group': 'default' }, { 'key': 'Password', 'value': 'Passwort', 'group': 'default' } ];

var res = Object.assign({},...languagePack.map(({key,value}) => ({[key]:value})))

console.log(res)


2

คุณสามารถใช้ ES6 Mapสำหรับการใช้งานที่Object.fromEntriesสามารถแปลงกลับไปmapObject

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับแผนที่

let languagePack=
[{
  'key': 'Username',
  'value': 'Benutzername',
  'group': 'default'
},
{
  'key': 'Password',
  'value': 'Passwort',
  'group': 'default'
}];

let map = new Map();

languagePack.forEach((val)=>{
  map.set(val.key, val.value);
})
languagePack = Object.fromEntries(map);
console.log(languagePack);

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