發布於 2023-06-30

更新於 2023-06-30

程式

約3279字 (17分鐘閱讀)

將陣列 (Array) 轉換為物件 (Object)

Title Image

前言 - Prologue

陣列和物件是 JavaScript 中最常見和重要的資料結構之一。陣列提供了順序集合的功能,而物件則提供了鍵值對的功能。然而有時候,我們需要將陣列轉換為物件,以便更好地組織和處理數據。以下將介紹幾種常見的方法來實現這一轉換。

正文 - Main text

接下來將介紹下列十一種方法,從 ECMAScript 5(ES5)~ ECMAScript 2019(ES10)以及 JavaScript 的基本語法等,已知能做到將陣列轉換為物件的方法一一統整。

  • reduce()
  • forEach()
  • for Loop
  • map() & Object.assign()
  • Object.fromEntries()
  • Destructuring Assignment & Object Literal
  • Spread syntax
  • for...of
  • reduceRight()
  • Array.from()
  • Recursive function
方法一:reduce()

ES 版本:reduce() 方法從 ECMAScript 5(ES5)(2009年) 開始引入。

reduce() 方法在陣列的每個元素上執行一個回調函式,將陣列轉換為一個值。

範例:

a. 只有一個陣列

const arr = ['apple', 'banana', 'orange'];
const obj = arr.reduce((acc, curr, index) => {
  acc[index] = curr;
  return acc;
}, {});

console.log(obj);

輸出結果:

{ 0: 'apple', 1: 'banana', 2: 'orange' }

b. 包含屬性名稱與屬性值在同一個陣列

const arr = ['name', 'John', 'age', 30, 'gender', 'male'];
const obj = arr.reduce((acc, curr, index, array) => {
  if (index % 2 === 0) {
    acc[curr] = array[index + 1];
  }
  return acc;
}, {});

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }

c. 兩個陣列,一個是屬性名稱,另一個是屬性值

const keys = ['name', 'age', 'gender'];
const values = ['John', 30, 'male'];
const obj = keys.reduce((acc, curr, index) => {
  acc[curr] = values[index];
  return acc;
}, {});

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }
方法二:forEach()

ES 版本:forEach() 方法從 ECMAScript 5(ES5)(2009年) 開始引入。

forEach() 方法對陣列的每個元素執行一個回調函式。

範例:

a. 只有一個陣列

const arr = ['apple', 'banana', 'orange'];
const obj = {};
arr.forEach((value, index) => {
  obj[index] = value;
});

console.log(obj);

輸出結果:

{ 0: 'apple', 1: 'banana', 2: 'orange' }

b. 包含屬性名稱與屬性值在同一個陣列

const arr = ['name', 'John', 'age', 30, 'gender', 'male'];
const obj = {};
let propertyName = '';
arr.forEach((value, index) => {
  if (index % 2 === 0) {
    propertyName = value;
  } else {
    obj[propertyName] = value;
  }
});

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }

c. 兩個陣列,一個是屬性名稱,另一個是屬性值

const keys = ['name', 'age', 'gender'];
const values = ['John', 30, 'male'];
const obj = {};
keys.forEach((key, index) => {
  obj[key] = values[index];
});

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }
方法三:for Loop

ES 版本:for 迴圈是 JavaScript 語言的基本結構,與特定的 ES 版本無關。(嚴格來說是 ES1(1997年))

使用 for 迴圈遍歷陣列元素並建立物件。

範例:

a. 只有一個陣列

const arr = ['apple', 'banana', 'orange'];
const obj = {};
for (let i = 0; i < arr.length; i++) {
  obj[i] = arr[i];
}

console.log(obj);

輸出結果:

{ 0: 'apple', 1: 'banana', 2: 'orange' }

b. 包含屬性名稱與屬性值在同一個陣列

const arr = ['name', 'John', 'age', 30, 'gender', 'male'];
const obj = {};
let propertyName = '';
for (let i = 0; i < arr.length; i++) {
  if (i % 2 === 0) {
    propertyName = arr[i];
  } else {
    obj[propertyName] = arr[i];
  }
}

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }

c. 兩個陣列,一個是屬性名稱,另一個是屬性值

const keys = ['name', 'age', 'gender'];
const values = ['John', 30, 'male'];
const obj = {};
for (let i = 0; i < keys.length; i++) {
  obj[keys[i]] = values[i];
}

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }
方法四:map() & Object.assign()

ES 版本:map() 方法從 ECMAScript 5(ES5)(2009年) 開始引入,Object.assign() 方法從 ECMAScript 6(ES6)(2015年) 開始引入。

map() 方法用於遍歷陣列並返回新的陣列,Object.assign() 方法用於將多個物件合併為一個新物件。

範例:

a. 只有一個陣列

const arr = ['apple', 'banana', 'orange'];
const obj = Object.assign({}, arr.map((value, index) => ({ [index]: value })));

console.log(obj);

輸出結果:

{ 0: 'apple', 1: 'banana', 2: 'orange' }

b. 包含屬性名稱與屬性值在同一個陣列

const arr = ['name', 'John', 'age', 30, 'gender', 'male'];
const obj = Object.assign({}, ...arr.map((value, index, array) => {
  if (index % 2 !== 0) {
    return { [array[index - 1]]: value };
  }
}));

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }

c. 兩個陣列,一個是屬性名稱,另一個是屬性值

const keys = ['name', 'age', 'gender'];
const values = ['John', 30, 'male'];
const obj = Object.assign({}, ...keys.map((key, index) => ({ [key]: values[index] })));

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }
方法五:Object.fromEntries()

ES 版本:Object.fromEntries() 方法從 ECMAScript 2019(ES10)開始引入。

Object.fromEntries() 方法將包含鍵值對的陣列轉換為物件。

範例:

a. 兩層陣列

const arr = [['name', 'John'], ['age', 30], ['gender', 'male']];
const obj = Object.fromEntries(arr);

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }

b. 包含屬性名稱與屬性值在同一個陣列

const arr = ['name', 'John', 'age', 30, 'gender', 'male'];
const obj = Object.fromEntries(
  arr.reduce((entries, value, index, array) => {
    if (index % 2 === 0) {
      entries.push([value, array[index + 1]]);
    }
    return entries;
  }, [])
);

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }

c. 兩個陣列,一個是屬性名稱,另一個是屬性值

const keys = ['name', 'age', 'gender'];
const values = ['John', 30, 'male'];
const obj = Object.fromEntries(keys.map((key, index) => [key, values[index]]));

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }
方法六:Destructuring Assignment & Object Literal

ES 版本:解構賦值(Destructuring Assignment)從 ECMAScript 6(ES6)開始引入,物件字面值(Object Literal)是 JavaScript 語言的基本語法,沒有特定的 ES 版本與之相關。

使用解構賦值來提取陣列的值,並結合物件字面量來建立物件。

範例:

a. 只有一個陣列

const arr = ['apple', 'banana', 'orange'];
const obj = arr.reduce((acc, curr, index) => {
  return { ...acc, [index]: curr };
}, {});

console.log(obj);

輸出結果:

{ 0: 'apple', 1: 'banana', 2: 'orange' }

b. 包含屬性名稱與屬性值在同一個陣列

const arr = ['name', 'John', 'age', 30, 'gender', 'male'];
const obj = {};
for (let i = 0; i < arr.length; i += 2) {
  const [key, value] = arr.slice(i, i + 2);
  obj[key] = value;
}

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }

c. 兩個陣列,一個是屬性名稱,另一個是屬性值

const keys = ['name', 'age', 'gender'];
const values = ['John', 30, 'male'];
const obj = keys.reduce((acc, key, index) => {
  return { ...acc, [key]: values[index] };
}, {});

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }
方法七:Spread syntax

ES 版本:展開語法(Spread syntax)從 ECMAScript 6(ES6)開始引入。

使用展開語法將陣列展開,並結合物件字面量來建立物件。

範例:

a. 只有一個陣列

const arr = ['apple', 'banana', 'orange'];
const obj = { ...arr };

console.log(obj);

輸出結果:

{ 0: 'apple', 1: 'banana', 2: 'orange' }

b. 包含屬性名稱與屬性值在同一個陣列

const arr = ['name', 'John', 'age', 30, 'gender', 'male'];
const obj = {};
for (let i = 0; i < arr.length; i += 2) {
  const [key, value] = arr.slice(i, i + 2);
  obj[key] = value;
}

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }

c. 兩個陣列,一個是屬性名稱,另一個是屬性值

const keys = ['name', 'age', 'gender'];
const values = ['John', 30, 'male'];
const obj = { ...keys.map((key, index) => ({ [key]: values[index] })) };

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }
方法八:for...of

ES 版本:for...of 迴圈從 ECMAScript 6(ES6)開始引入。

使用 for...of 迴圈遍歷陣列元素並建立物件。

範例:

a. 只有一個陣列

const arr = ['apple', 'banana', 'orange'];
const obj = {};
let index = 0;
for (const item of arr) {
  obj[index] = item;
  index++;
}

console.log(obj);

輸出結果:

{ 0: 'apple', 1: 'banana', 2: 'orange' }

b. 包含屬性名稱與屬性值在同一個陣列

const arr = ['name', 'John', 'age', 30, 'gender', 'male'];
const obj = {};
let propertyName = '';
for (const item of arr) {
  if (propertyName === '') {
    propertyName = item;
  } else {
    obj[propertyName] = item;
    propertyName = '';
  }
}

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }

c. 兩個陣列,一個是屬性名稱,另一個是屬性值

const keys = ['name', 'age', 'gender'];
const values = ['John', 30, 'male'];
const obj = {};
for (const [index, key] of keys.entries()) {
  obj[key] = values[index];
}

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }
方法九:reduceRight()

ES 版本:reduceRight() 方法從 ECMAScript 5(ES5)(2009年) 開始引入。

reduceRight() 方法從陣列的最後一個元素開始遍歷,將每個元素與累加器結合,並返回最終的值。

範例:

a. 只有一個陣列

const arr = ['apple', 'banana', 'orange'];
const obj = arr.reduceRight((acc, curr, index) => {
  return { ...acc, [index]: curr };
}, {});

console.log(obj);

輸出結果:

{ 0: 'apple', 1: 'banana', 2: 'orange' }

b. 包含屬性名稱與屬性值在同一個陣列

const arr = ['name', 'John', 'age', 30, 'gender', 'male'];
const obj = arr.reduceRight((acc, curr, index, array) => {
  if (index % 2 === 0) {
    return { ...acc, [array[index + 1]]: curr };
  }
  return acc;
}, {});

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }

c. 兩個陣列,一個是屬性名稱,另一個是屬性值

const keys = ['name', 'age', 'gender'];
const values = ['John', 30, 'male'];
const obj = keys.reduceRight((acc, key, index) => {
  return { ...acc, [key]: values[index] };
}, {});

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }
方法十:Array.from()

ES 版本:Array.from() 方法從 ECMAScript 6(ES6)開始引入。

Array.from() 方法將類陣列對象或可迭代對象轉換為真正的陣列,然後可以使用其他方法進行處理。

範例:

a. 只有一個陣列

const arr = ['apple', 'banana', 'orange'];
const obj = Array.from(arr, (value, index) => ({ [index]: value })).reduce((acc, curr) => ({ ...acc, ...curr }), {});

console.log(obj);

輸出結果:

{ 0: 'apple', 1: 'banana', 2: 'orange' }

b. 包含屬性名稱與屬性值在同一個陣列

const arr = ['name', 'John', 'age', 30, 'gender', 'male'];
const obj = Array.from(arr, (value, index, array) => {
  if (index % 2 !== 0) {
    return { [array[index - 1]]: value };
  }
}).reduce((acc, curr) => ({ ...acc, ...curr }), {});

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }

c. 兩個陣列,一個是屬性名稱,另一個是屬性值

const keys = ['name', 'age', 'gender'];
const values = ['John', 30, 'male'];
const obj = Array.from(keys, (key, index) => ({ [key]: values[index] })).reduce((acc, curr) => ({ ...acc, ...curr }), {});

console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }
方法十一:Recursive function

ES 版本:遞迴函式的概念在 JavaScript 中是通用的,並不特定於特定的 ES 版本。

使用遞迴函式將陣列轉換為物件,並處理嵌套陣列的情況。

範例:

a. 只有一個陣列

function arrayToObject(arr) {
  const obj = {};
  for (let i = 0; i < arr.length; i++) {
    obj[i] = arr[i];
  }
  return obj;
}

const arr = ['John', 30, 'male'];
const obj = arrayToObject(arr);
console.log(obj);

輸出結果:

{ 0: 'John', 1: 30, 2: 'male' }

b. 包含屬性名稱與屬性值在同一個陣列

function arrayToObject(arr) {
  const obj = {};
  if (Array.isArray(arr)) {
    for (let i = 0; i < arr.length; i += 2) {
      const key = arr[i];
      const value = arr[i + 1];
      if (Array.isArray(value)) {
        obj[key] = arrayToObject(value);
      } else {
        obj[key] = value;
      }
    }
  }
  return obj;
}

const arr = ['name', 'John', 'age', 30, 'hobbies', ['reading', 'cooking']];
const obj = arrayToObject(arr);
console.log(obj);

輸出結果:

{ name: 'John', age: 30, hobbies: ['reading', 'cooking'] }

c. 兩個陣列,一個是屬性名稱,另一個是屬性值

function arrayToObject(keys, values) {
  const obj = {};
  for (let i = 0; i < keys.length; i++) {
    obj[keys[i]] = values[i];
  }
  return obj;
}

const keys = ['name', 'age', 'gender'];
const values = ['John', 30, 'male'];
const obj = arrayToObject(keys, values);
console.log(obj);

輸出結果:

{ name: 'John', age: 30, gender: 'male' }

個人使用範例 - Personal Usage Example

需求:讓一個陣列 ['1', '1111111'] 變成物件 { a: '1', b: '1111111'}

使用 ES6 的解構賦值(Destructuring Assignment)和物件字面值(Object Literal)的語法來將一個陣列轉換為物件。

const arr = ['1', '1111111'];
const [a, b] = arr;
const obj = { a, b };

console.log(obj);

// Output: { a: '1', b: '1111111' }

精簡後:

const arr = ['1', '1111111'];
const obj = (([a, b]) => ({ a, b }))(arr);

console.log(obj);

// Output: { a: '1', b: '1111111' }

或是使用 Object.fromEntries() 方法將由陣列組成的鍵值對列表轉換為物件。

const arr = ['1', '1111111'];
const obj = Object.fromEntries([
  ['a', arr[0]],
  ['b', arr[1]],
]);

console.log(obj);

// Output: { a: '1', b: '1111111' }

而關於這兩種哪一種比較好呢?

這兩種方法都可以將陣列轉換為物件,取決於個人偏好和程式碼的可讀性。

第一種方法使用解構賦值和物件字面值簡化的語法,可以在一行內完成操作。這種寫法相對緊湊,對於熟悉這種語法的開發者來說可能更直觀。

第二種方法使用 Object.fromEntries() 方法將由陣列組成的鍵值對列表轉換為物件。這種寫法明確地將每個鍵值對指定為獨立的元素,可能更易於理解。

在選擇使用哪種方法時,可以考慮以下因素:

  • 個人偏好:選擇最舒適和習慣的寫法。
  • 團隊風格:如果正在開發團隊中,遵從團隊約定和共享的程式碼風格指南。
  • 可讀性:選擇能夠讓代碼清晰、易於理解的寫法。

總之這兩種方法都是有效的,具體選擇取決於對語法的舒適度和代碼的可讀性需求。

後記 - Epilogue

每種方法都有其優點和用途,取決於需求和程式碼的上下文。

參考資料 - Reference

[1] JavaScript Versions

https://www.w3schools.com/js/js_versions.asp

[2] MDN Web Docs

https://developer.mozilla.org/en-US/

將陣列 (Array) 轉換為物件 (Object)

https:///blog/69

作者

Kama

Read more from 程式
lightbox-image
Toggle Button - Red Pandas Icons by svgrepo.com

Copyrights © 2023 Kama, All Rights Reserved.