You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何以不可变方式过滤作为对象属性的数组?

如何以不可变方式过滤作为对象属性的数组

我明白你的问题了——当前的代码只是筛选出包含匹配联系人的分组,但每个分组里的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:50:31