【问题标题】:Javascript how to push a new element from an initial array to each array inside an array of arrays at the same index?Javascript如何将新元素从初始数组推送到相同索引的数组数组中的每个数组?
【发布时间】:2020-07-30 21:01:01
【问题描述】:

我想使用两者的索引从另一个数组向一个数组添加新属性。

例如,假设我有以下数组:

initArray = [
  { name: 'John', family: 'Doe'},
  { name: 'Joanna', family: 'Doe'}
];

以及我想从中取出并推入initArray的数组:

genderArray = [
  { gender: 'Male' },
  { gender: 'Female' }
];

我需要的是一个像这样的最终数组:

initArray = [
  { name: 'John', family: 'Doe', gender: 'Male'},
  { name: 'Joanna', family: 'Doe', gender: 'Female'}
];

我尝试了以下方法:

ngOnInit() {
  Object.keys(this.genderArray).forEach((idx) => {
    console.log(this.initArray)
    this.initArray[idx].push(this.genderArray)
  });

  console.log(this.initArray)
}

但是它返回了一个错误:

错误:_this.initArray[idx].push 不是函数

这是stackblitz

【问题讨论】:

  • 你推送到一个元素,而不是一个数组
  • 看起来您正在尝试推送到一个对象。该对象是数组的一部分。

标签: javascript arrays types


【解决方案1】:

问题是你试图在一个对象上使用array.push(),这是行不通的。

相反,您可以使用 for 循环遍历数组,并通过为其分配一个值来简单地将“性别”类别添加到该索引,即另一个数组中该索引处的性别:

initArray = [
  { name: 'John', family: 'Doe'},
  { name: 'Joanna', family: 'Doe'}
];

genderArray = [
  { gender: 'Male' },
  { gender: 'Female' }
];

for (var i = 0; i < initArray.length; i++) {
  initArray[i].gender = genderArray[i].gender;
}

console.log(initArray);

或者,您可以使用array.forEach()

initArray = [
  { name: 'John', family: 'Doe'},
  { name: 'Joanna', family: 'Doe'}
];

genderArray = [
  { gender: 'Male' },
  { gender: 'Female' }
];

initArray.forEach(addGender);

function addGender(_, i) {
  initArray[i].gender = genderArray[i].gender;
}

console.log(initArray);

【讨论】:

  • 如果您使用不支持 ES5 的环境,请使用此选项。否则它会有点难以阅读 - 并且 i 变量将在整个函数的范围内与您保持一致。
  • 如果我想将其从for (var...) 更改为for (const of ...),在这种情况下如何访问索引? @raina77ow
  • @alim1990 我不太确定在这里使用for...of 是否是个好主意——它是为了在索引不相关时迭代元素而创建的,而这里的情况并非如此。为什么不直接使用 .forEach()?此函数的目的与大小写完全匹配:对原始数组的每个元素执行某些操作,但不返回结果。
  • @raina77ow 我在回答中添加了一个使用array.forEach() 的解决方案
【解决方案2】:

首先,您不应该推送到initArray:您不initArray 添加元素,而是向其每个元素添加属性

一种可能的方法:

Object.assign(this.initArray[idx], this.genderArray[idx]);

...或者,如果出于某种原因您想要创建一个全新的“丰富”对象数组,而不是直接修改对象:

this.initArray[idx] = {...this.initArray[idx], ...this.genderArray[idx]};

其次,不要使用 Object.keys() 来遍历数组:如果您在函数内部进行所有转换,请使用 forEach(),如果您返回一个新元素并想要一个新元素,请使用 map数组到底。

所以你的函数可能看起来像这样:

ngOnInit() {
  this.genderArray.forEach((element, index) => {
    Object.assign(this.initArray[index], element);
  });

  console.log(this.initArray)
}

...或...

ngOnInit() {
  this.initArray = this.initArray.map((element, index) => {
     { ...element, ...this.genderArray[index] }
  });

  console.log(this.initArray)
}

就我个人而言,我总是发现代码 'x = x.map(transformer())` 非常可疑(如果无论如何都要重新分配,为什么不使用 forEach?),但这取决于实现风格的选择。


如果数组的元素中有多个属性要“混合”,但你只想取一个,你可以直接去:

Object.assign(this.initArray[idx], { gender: this.genderArray[idx].gender });

...在赋值中使用解构:

const { gender } = this.genderArray[idx]; 
Object.assign(this.initArray[idx], { gender });

...或者像我们在过去没有语法糖的好日子那样硬着头皮直接做分配:

this.initArray[idx].gender = this.genderArray[idx].gender;

在这种特殊情况下,最后一个看起来实际上是最好的方法。它的缺点是必须重复属性名称,但如果您希望道具在源数组和目标数组中以不同的方式命名,这也可能会派上用场。

【讨论】:

  • 酷,但是如果genderArray有2个属性,我只需要一个推送到initArray
  • 在这种情况下,您应该将 genderArray[index] 引用替换为非常直接的{ gender: genderArray[index].gender ,或者以不同的方式进行 - 但也许更清楚 - 我会在答案中描述。跨度>
【解决方案3】:

您可以通过reduce 方法使用... 扩展运算符合并两个数组:

const result = initArray.reduce((a, c, i) => {
   a.push({...c, ...genderArray[i]})
   return a;
},[])

或单行版本:

const result = initArray.reduce((a, c, i) => (a.push({...c, ...genderArray[i]}), a),[])

一个例子:

let initArray = [
  { name: 'John', family: 'Doe'},
  { name: 'Joanna', family: 'Doe'}
];

let genderArray = [
  { gender: 'Male' },
  { gender: 'Female' }
];

const result = initArray.reduce((a, c, i) => {
   a.push({...c, ...genderArray[i]})
   return a;
},[])

console.log(result)

【讨论】:

    【解决方案4】:

    您实际上是在尝试“合并”两个数组中的对象。

    有很多方法可以实现这一点,但我认为最清晰的一种是使用Array.mapObject.assign 函数:

    const initArray = [
      { name: 'John', family: 'Doe'},
      { name: 'Joanna', family: 'Doe'}
    ];
    const genderArray = [
      { gender: 'Male' },
      { gender: 'Female' }
    ];
    
    const ans = initArray.map((person, index) => {
      const genderedPerson = Object.assign({}, person, genderArray[index]);
      return genderedPerson;
    });
    console.log(ans);
    • Array.map 迭代一个数组并修改其元素。
    • Object.assign 扩展一个对象,为其添加来自另一个对象的附加属性。

    【讨论】:

    • 严格来说Array.map不应该修改原始数组的元素;它用于基于原始的某些转换创建一个新集合。所以可以使用类似... return { ... person, genderArray[index] } 的东西。
    • @raina77ow 你是对的,我修改了我的答案,所以genderedPerson 的生成也不会修改initArray。我喜欢扩展运算符,但我认为显式语法对初学者来说更清晰
    • Spread op 很好,但它经常被误用,每次使用它而不是 Object.assign 时都会无缘无故地增加一个小惩罚。这里有更多关于它的信息 - medium.com/better-programming/…
    猜你喜欢
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 1970-01-01
    • 1970-01-01
    • 2012-07-10
    • 2020-07-14
    相关资源
    最近更新 更多