从数组创建对象

IT技术 javascript arrays ecmascript-6 javascript-objects
2021-01-29 21:04:35

我想从数组内的列表创建一个对象。我有一个动态数组,应该如下所示:

var dynamicArray = ["2007", "2008", "2009", "2010"];

我想用一些 JavaScript ES6 创建一个这样的对象:

const obj = {
    2007: {
        x: width / 5,
        y: height / 2
    },
    2008: {
        x: (2 / 5) * width,
        y: height / 2
    },
    2009: {
        x: (3 / 5) * width,
        y: height / 2
    },
    2010: {
        x: (4 / 5) * width,
        y: height / 2
    }
}

不要担心内部对象。我只想创建一个这样的结构:

 obj = {
      2007: ...,
      2008: ...,
      ...
    }

请帮忙,谢谢。

6个回答

简单地

 const obj = {};

 for (const key of yourArray) {
      obj[key] = whatever;
 }

或者如果您更喜欢“功能性”风格:

 const obj = yourArray.reduce((o, key) => Object.assign(o, {[key]: whatever}), {});

使用现代对象扩展运算符:

const obj = yourArray.reduce((o, key) => ({ ...o, [key]: whatever}), {})

例子:

[
  { id: 10, color: "red" },
  { id: 20, color: "blue" },
  { id: 30, color: "green" }
].reduce((acc, cur) => ({ ...acc, [cur.color]: cur.id }), {})

输出:

{red: 10, blue: 20, green: 30}

下面是它的工作原理:

reduce用一个空对象({}最后为空)初始化,因此第一个迭代变量是acc = {} cur = { id: 10, color: "red" }函数返回一个对象——这就是函数体被括在括号中的原因=> ({ ... })Spread 运算符在第一次迭代时不做任何事情,因此red: 10设置为第一项。

在第二次迭代变量是acc = { red: 10 } cur = { id: 20, color: "blue" }此处展开运算符展开 acc并且函数返回{ red: 10, blue: 20 }

第三次迭代acc = { red: 10, blue: 20 } cur = { id: 30, color: "green" },所以当acc在对象内部传播,我们的函数返回最终值。

关于“功能风格”方法,在每次迭代中复制对象似乎有点矫枉过正。我建议添加到新对象上:yourArray.reduce((o, key) => { o[key] = whatever; return o; }, {}). 其他一切看起来都很棒!
2021-03-15 21:04:35
@cameck:谢谢,帖子是CW,随意编辑。
2021-03-20 21:04:35
谢谢!它按要求工作。我从来不知道array.reduce函数。
2021-03-21 21:04:35
如果你更喜欢函数式风格,我也喜欢,你应该使用const. 实际上,无论如何您都应该使用它。此外,如果您可以访问 ES Next rest/spread 语法(例如通过 TypeScript 或 Babel),您可以编写const obj = yourArray.reduce((o, key) => ({ ...o, [key]: whatever}), {})甚至避免改变种子:p
2021-03-30 21:04:35
@AluanHaddad:好建议,转成CW,随意编辑。
2021-04-03 21:04:35

Object.fromEntries来自 ECMAScript 2019的新,可以更轻松地将数组中的值转换为对象中的键,如下所示

const dynamicArray = ["2007", "2008", "2009", "2010"];
const obj = Object.fromEntries(
  dynamicArray.map(year => [year, {
    something: "based",
    on: year
  }])
)

console.log(obj)

谢谢!你救了我的一天!使用数组 unshift 和 splice 可以做同样的事情吗?
2021-04-01 21:04:35

在 js 中使用 es6 减少数组函数我这样做

let x = [1,2,3]
let y = x.reduce((acc, elem) => {
  acc[elem] = elem // or what ever object you want inside
  return acc
}, {})
console.log(y) // {1:1, 2:2, 3:3}
甚至更短: [1, 2, 3].reduce((x, y)=>(x[y] = 1, x), {})
2021-03-23 21:04:35
@exebook 你能解释一下reducex的返回函数内部在做什么吗?
2021-04-10 21:04:35
var keys = ['key1', 'key2', 'key3']

var object = Object.assign({}, ...Object.entries({...keys}).map(([a,b]) => ({ [b]: 'someValue' })))
console.log(object)

这将产生

{ key1: 'someValue', key2: 'someValue', key3: 'someValue' }

我发现您实际上可以Object.assign()直接与扩展运算符一起使用。无需使用 areducemap函数引入更多复杂性

简单地做Object.assign(...yourArray, {}),你会得到你想要的结果。如果您想将您的对象数组合并到另一个对象中,您也可以调用Object.assign(...yourArray, yourObject)它,它也可以正常工作。

您也可以使用相同的方法将两个数组合并为一个对象,即使其中一个数组不包含对象而只包含原始值 - 但是如果您这样做,您需要确保至少一个数组只包含对象作为原语将默认为其索引作为key,因此如果存在重复键,您将收到错误。

然而,对于 OP 而言,没有发生此类错误的风险,因为他正在与空对象合并,这是最安全的方式。

const arr = [
  { a: 0 },
  { c: 1 },
  { e: 2 },
];

const obj = Object.assign({}, ...arr);

console.log(obj)

// Results to:
// Object { a: 0, c: 1, e: 2 }
根据object.assign()需要编辑目标对象作为第一个参数。以前 ( object.assign(...arr, {})){}是多余的,返回的对象是数组的第一个条目arr我不认为它是为了改变arr
2021-03-15 21:04:35
即使在已接受的答案上,对象分配解决方案也是题外话,因为 op 是从字符串数组而不是对象数组开始的
2021-03-28 21:04:35
我只是将它用作如何使用它的示例 - 但它也适用于诸如 OP 请求的字符串数组,正如我提到的那样,它将默认索引的键,因此它将是 { 0: 'string1', 1: 'string2' }
2021-03-28 21:04:35