如何以不可变方式过滤作为对象属性的数组?
如何以不可变方式过滤作为对象属性的数组
我明白你的问题了——当前的代码只是筛选出包含匹配联系人的分组,但每个分组里的contacts数组还是原封不动的完整数组,没有只保留符合搜索条件的联系人,而且你希望整个过程是不可变的,也就是完全不修改原有的contactGroups数组和里面的对象,返回全新的结构。
原代码的问题分析
你的filter只作用在contactGroups层面:判断每个分组里是否有至少一个匹配的联系人,如果有就保留这个分组,但并没有对分组内的contacts做过滤。而且因为对象引用的关系,返回的分组里的contacts还是指向原数组的引用,没有生成新的过滤后的数组。
解决方案:结合filter和map实现不可变过滤
要实现需求,我们需要两步:
- 先处理每个分组,过滤出其中符合搜索条件的联系人,同时创建新的分组对象(不修改原对象)
- 再过滤掉那些没有匹配联系人的分组
这样既保留了符合条件的分组,又过滤了每个分组内的联系人,同时完全不修改原数据,满足不可变性要求。
TypeScript 实现
public transform(contactGroups: ContactGroup[], searchText: string): ContactGroup[] { if (!contactGroups) { return []; } if (searchText === undefined) { return contactGroups; } // 提前转换搜索文本为小写,避免重复计算 const lowerSearchText = searchText.toLowerCase(); return contactGroups .map(group => { // 过滤当前分组内匹配的联系人 const filteredContacts = group.contacts.filter(contact => contact.displayName && contact.displayName.toLowerCase().includes(lowerSearchText) ); // 返回新的分组对象,保留原属性的同时替换contacts为过滤后的数组 return { ...group, contacts: filteredContacts }; }) // 过滤掉没有匹配联系人的分组 .filter(group => group.contacts.length > 0); }
JavaScript 实现
function transform(contactGroups, searchText) { if (!contactGroups) { return []; } if (searchText === undefined) { return contactGroups; } const lowerSearchText = searchText.toLowerCase(); return contactGroups .map(function(group) { const filteredContacts = group.contacts.filter(function(contact) { return contact.displayName && contact.displayName.toLowerCase().includes(lowerSearchText); }); // 展开原分组对象,创建新对象并替换contacts属性 return { ...group, contacts: filteredContacts }; }) .filter(function(group) { return group.contacts.length > 0; }); };
关键细节说明
- 不可变性保障:使用对象展开运算符
{ ...group }创建新的分组对象,而非修改原对象;filter返回全新的数组,不会改变原contacts数组,原数据全程无修改。 - 性能优化:提前将
searchText转为小写,避免在每一次联系人过滤中重复执行转换操作,提升代码效率。 - 逻辑清晰:先通过
map处理所有分组的联系人过滤,再用filter剔除无效分组,避免重复遍历联系人列表。
用你的示例数据测试,若搜索文本为"sam",返回的结果会是:
[{ "letter":"S", "contacts":[ { "id":"173", "rawId":null, "displayName":"sam", "name":{ "givenName":"sam", "formatted":"sam" }, "nickname":null, "phoneNumbers":null, "emails":[ { "id":"955", "pref":false, "value":"sam@xyz.com", "type":"other" } ], "addresses":null, "ims":null, "organizations":null, "birthday":null, "note":"", "photos":null, "categories":null, "urls":null } ] }]
内容的提问来源于stack exchange,提问作者Vivek S
相关产品推荐
相关产品推荐

