以不可变的方式过滤对象属性中的数组

3

我如何以不可变的方式过滤一个对象属性中的数组?例如:

public transform(contactGroups: ContactGroup[], searchText: string): ContactGroup[] {
    if (!contactGroups) {
        return [];
    }
    if (searchText === undefined) {
        return contactGroups;
    }
    return contactGroups.filter((contactGroup: ContactGroup) => {
        return contactGroup.contacts.filter((contact: Contact) => {
            return contact.displayName && contact.displayName.toLowerCase().includes(searchText.toLowerCase())
        }).length > 0;
    });
}

在上面的示例中,contactGroup.contacts包含数组中的所有项,但由于对象引用,不包含过滤结果。
非常感谢您的帮助。 谢谢。

function transform(contactGroups, searchText) {
        if (!contactGroups) {
            return [];
        }
        if (searchText === undefined) {
            return contactGroups;
        }
        return contactGroups.filter(function (contactGroup) {
            return contactGroup.contacts.filter(function (contact) {
                return (contact.displayName && contact.displayName.toLowerCase().includes(searchText.toLowerCase()));
            }).length > 0;
        });
    };
 
 var contactGroups = [{  
   "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
      },
      {  
            "id":"1717",
            "rawId":null,
            "displayName":"Sat33",
            "name":{  
               "givenName":"Sat33",
               "formatted":"Sat33 "
            },
            "nickname":null,
            "phoneNumbers":[  
               {  
                  "id":"5521",
                  "pref":false,
                  "value":"1133",
                  "type":"work"
               }
            ],
            "emails":null,
            "addresses":null,
            "ims":null,
            "organizations":null,
            "birthday":null,
            "note":null,
            "photos":null,
            "categories":null,
            "urls":null
      },
      {  
            "id":"1712",
            "rawId":null,
            "displayName":"Server1234",
            "name":{  
               "givenName":"Server1234",
               "formatted":"Server1234 "
            },
            "nickname":null,
            "phoneNumbers":[  
               {  
                  "id":"5509",
                  "pref":false,
                  "value":"1234",
                  "type":"mobile"
               }
            ],
            "emails":null,
            "addresses":null,
            "ims":null,
            "organizations":null,
            "birthday":null,
            "note":null,
            "photos":null,
            "categories":null,
            "urls":null
      }
   ]
}]

console.log(transform(contactGroups, 'ver'))

它应该只返回包含联系对象'Server1234'的contactGroup,因为搜索的字符串是'ver',但它仍然返回包含所有联系对象的contactGroup。

您期望的结果是带有筛选后的联系人列表的联系人组过滤列表吗? - Ricardo
如果不了解你正在过滤和期望输出的数据结构,这个问题很难回答。请分享一个能够演示你问题的工作代码片段。 - gurvinder372
请告诉我是否需要更多信息。 - Vivek S
@gurvinder372 添加了代码片段。 - Vivek S
2个回答

2
你可以尝试这个解决方案。
class ContactGroup {
    contacts: Contact[]
}
class Contact {
    displayName: string
}
function transform(contactGroups: ContactGroup[], searchText: string): ContactGroup[] {
    if (!contactGroups) {
        return [];
    }
    if (searchText === undefined) {
        return contactGroups;
    }
    return contactGroups.map((contactGroup: ContactGroup) => {
        return {
            ...contactGroup,
            contacts: contactGroup.contacts.filter((contact: Contact) => {
                return contact.displayName && contact.displayName.toLowerCase().includes(searchText.toLowerCase())
            })
        }
    }).filter((contactGroup: ContactGroup) => {
        return contactGroup.contacts.length > 0
    })
}

哇!运行得非常好。谢谢你,Ricardo。 - Vivek S

0

您可以清空传递的数组并将筛选后的元素推入其中。以下是您代码的简化版本:

function transform(contactGroups, searchText) { 
    var filtered = contactGroups.filter(e => e.name.includes(searchText));
    contactGroups.splice(0, contactGroups.length);
    contactGroups.push(...filtered);
    return filtered;  // <-- if still needed
}

var contacts = [{name: 'abc'}, {name: 'abcc'}, {name: 'xyz'}];
transform(contacts, 'abc');
console.log(contacts);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接