TypeScript/JavaScript中的高级过滤嵌套元素

68bkxrlz  于 2023-01-27  发布在  TypeScript
关注(0)|答案(1)|浏览(147)

给定以下结构和数据:

interface GrandChild {
    id: number,
    values: Array<string>,
}

interface Child {
    id: number,
    subItems: Array<GrandChild>
}

interface Foo {
    items: Array<Child>
}

const data: Foo = {
    items: [
        { id: 1, subItems: [ { id: 10, values: ['10', '100'] }, { id: 11, values: ['11', '110', '1100'] } ] },
        { id: 2, subItems: [ { id: 20, values: ['REMOVE', 'REMOVE'] }, { id: 21, values: ['REMOVE'] } ] },
        { id: 3, subItems: [ { id: 30, values: ['REMOVE'] }, { id: 31, values: ['REMOVE'] }, { id: 32, values: ['REMOVE', '32'] } ] },
    ]
};

如何使用Array的方法(filter、map、some等)来实现以下结果?

const expected: Foo = {
    items: [
        { id: 1, subItems: [ { id: 10, values: ['10', '100'] }, { id: 11, values: ['11', '110', '1100'] } ] },
        { id: 3, subItems: [ { id: 32, values: ['32'] } ] },
    ]
}

到目前为止,我过滤了结果数据,删除了不需要的元素,如下所示:

const filteredData: Foo = {
    ...data,
    items: data.items.map(item => ({
        ...item,
        subItems: item.subItems.map(subItem => ({
            ...subItem,
            values: subItem.values.filter(value => value !== 'REMOVE')
        }))
    }))
}

结果:

{
    items: [
        { id: 1, subItems: [ { id: 10, values: ['10', '100'] }, { id: 11, values: ['11', '110', '1100'] } ] },
        { id: 2, subItems: [ { id: 20, values: [] }, { id: 21, values: [] } ] },
        { id: 3, subItems: [ { id: 30, values: [] }, { id: 31, values: [] }, { id: 32, values: ['32'] } ] },
    ]
};

但是,我无法找到一种方法来删除空的subItems元素而不循环结果。
您可以在这里在线检查上述代码。

cbwuti44

cbwuti441#

如果你真的想只使用filtermap,在你的每个map后面添加一个filter来删除有一个空values数组的subItems和有一个空subItems数组的item

const filteredData = {
    ...data,
    items: data.items
        .map((item) => ({
            ...item,
            subItems: item.subItems
                .map((subItem) => ({
                    ...subItem,
                    values: subItem.values.filter((value) => value !== "REMOVE"),
                }))
                .filter(({ values }) => values.length > 0), // ***
        }))
        .filter(({subItems}) => subItems.length > 0),       // ***
};

但是:

  • map后接filter时,我总是问自己数据是否足够大,应该避免多次通过它。
  • 当我在做大量map调用的嵌套等工作时,我总是问自己,在以后阅读代码时,使用更简单、更小的循环是否会更清楚。

如果你对这两个问题中的一个或两个都回答"是",你可能会这样做:

const filteredData: Foo = {
    ...data,
    items: [],
};
for (const item of data.items) {
    const subItems: Array<GrandChild> = [];
    for (const subItem of item.subItems) {
        const values = subItem.values.filter((value) => value !== "REMOVE");
        if (values.length) {
            subItems.push({
                ...subItem,
                values,
            });
        }
    }
    if (subItems.length > 0) {
        filteredData.items.push({
            ...item,
            subItems,
        });
    }
}

相关问题