【问题标题】:Retrieve objects in array if property matches another array如果属性与另一个数组匹配,则检索数组中的对象
【发布时间】:2019-04-14 19:25:47
【问题描述】:

如果联系人中的 value 属性与 selectedContact 中的值匹配,我想创建一个包含联系人对象的新数组。有更简单的方法吗?

selectedContact: number[] = [0,2] //value
contacts: Contact[] = [{ 
  firstName:"Dan";
  lastName:"Chong";
  email:"danc@mail.com";
  value:0;
},
{ 
  firstName:"Mark";
  lastName:"Wong";
  email:"markw@mail.com";
  value:1;
},
{ 
  firstName:"Layla";
  lastName:"Sng";
  email:"layla@mail.com";
  value: 2;
}]

预期的最终结果:

newArray = [{ 
 firstName:"Dan";
 lastName:"Chong";
 email:"danc@mail.com";
 value:0;
},{ 
 firstName:"Layla";
 lastName:"Sng";
 email:"layla@mail.com";
 value:2;
}];

我目前的解决方案:

const newArray: Contact[] = [];
this.selectedContact.forEach(index => {
  newArray.push(this.contacts.find(c => c.value === index));
});

【问题讨论】:

  • 未能提及当前解决方案与预期结果有何不同或遇到任何错误
  • 肯定有更好的方法,但是你说的“更简单”是什么意思,你在找什么?
  • 您对“更简单”的标准是什么?很难想出更简单的方法。不过可能有更有效的方法,例如创建 contacts 的索引以供重复使用。
  • 对不起,我的意思是一种更有效的方法来执行此操作,而无需修改数组。当前的解决方案提供了所需的输出,但是否有更有效的方法,例如不使用 forEach 循环?

标签: javascript arrays typescript object angular6


【解决方案1】:

就性能而言,迭代 selectedContacts 而不是 contacts 会更好,尤其是因为 contacts 已编入索引(作为数组)并且您正在通过索引进行选择。

假设contacts的长度是NselectedContacts的长度是M

由于selectedContactscontacts 的子集,我们知道M <= N。 对于大型联系人数据库,这种差异可能很大。

问题中的代码:

this.selectedContact.forEach(index => {
  newArray.push(this.contacts.find(c => c.value === index));
});

具有O(M*N),因为它迭代selectedContactO(M),并且在每次迭代中它都会在contacts (O(N)) 中找到一个值。

已接受答案中的代码遍历contact (O(N)) 并在selectedContact 中查找值O(M)。这使得算法等效,O(N*M)

在您的示例中,您已经有了一种按号码查找联系人的廉价方法,因为 contacts 是一个数组,而您的索引只是数组中的索引。

这意味着你可以使用这样的代码:

return this.selectedContact.map(index => this.contacts[index]);

由于按索引访问数组元素具有O(1),因此它将具有O(M),这是大小中最小的。

如果您不能使用数组索引作为键,您可以使用其他数据结构,例如Map,其中 id 是键,联系人是值。这将具有相似的查找速度(大致为O(1))。

【讨论】:

  • 我明白了。谢谢你的详细解释!! :)
【解决方案2】:

您可以使用Array.prototype.filter()

filter() 方法创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。

Array.prototype.includes()

includes() 方法判断数组是否包含某个元素,根据需要返回真或假。

工作代码示例:

var selectedContact = [0,2];
var contacts = [{ 
  firstName: "Dan",
  lastName: "Chong",
  email: "danc@mail.com",
  value: 0
},
{ 
  firstName: "Mark",
  lastName: "Wong",
  email: "markw@mail.com",
  value: 1
},
{ 
  firstName: "Layla",
  lastName: "Sng",
  email: "layla@mail.com",
  value: 2
}]
let newArray =  contacts.filter(c => selectedContact.includes(c.value));

console.log(newArray);

【讨论】:

  • @iBlehhz——是的,但“有效”并不是衡量效率的标准。 ;-) 这在 selectedContacts 很小的情况下会很有效,但如果不是,索引解决方案可能会更好(假设可以收回创建索引的成本)。
猜你喜欢
  • 2022-11-21
  • 2020-04-09
  • 2020-04-06
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 2019-07-14
  • 1970-01-01
  • 2020-08-06
相关资源
最近更新 更多