如果属性与另一个数组匹配,则检索数组中的对象
Posted
技术标签:
【中文标题】如果属性与另一个数组匹配,则检索数组中的对象【英文标题】: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 循环? 【参考方案1】:就性能而言,迭代 selectedContacts
而不是 contacts
会更好,尤其是因为 contacts
已编入索引(作为数组)并且您正在通过索引进行选择。
假设contacts
的长度是N
,selectedContacts
的长度是M
。
由于selectedContacts
是contacts
的子集,我们知道M <= N
。
对于大型联系人数据库,这种差异可能很大。
问题中的代码:
this.selectedContact.forEach(index =>
newArray.push(this.contacts.find(c => c.value === index));
);
具有O(M*N)
,因为它迭代selectedContact
O(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 很小的情况下会很有效,但如果不是,索引解决方案可能会更好(假设可以收回创建索引的成本)。以上是关于如果属性与另一个数组匹配,则检索数组中的对象的主要内容,如果未能解决你的问题,请参考以下文章