过滤对象数组中的数组

问题描述 投票:0回答:2

我有一个看起来像这样的数组

var categorizedBooks = [
{
 name: "category1",
 books:[
        {name:"book1", bookContainerId: 1, active: true},
        {name:"book2", bookContainerId: 2, active: false},
        {name:"book3", bookContainerId: 2, active: true},
       ]
 },
{
 name: "category2",
 books:[
        {name:"book4", bookContainerId: 1, active: false},
        {name:"book5", bookContainerId: 3, active: true},
        {name:"book6", bookContainerId: 4, active: true},
       ]
 },
{
 name: "category3",
 books:[
        {name:"book7", bookContainerId: 1, active: false},
        {name:"book8", bookContainerId: 2, active: true},
        {name:"book9", bookContainerId: 4, active: false},
       ]
 },
{
 name: "category4",
 books:[
        {name:"book10", bookContainerId: 2, active: false},
        {name:"book11", bookContainerId: 2, active: false},
        {name:"book12", bookContainerId: 4, active: false},
       ]
 }

而且我想在看起来像这样的两个数组上过滤它们:

bookContainers: [1,3]
isActive: ['active', 'inactive] // an array of strings

这些来自输入,因此可以随时更改。因此,我想将bookContainers与他们的bookContainerId相匹配,并将'active'/'inactive'字符串数组与它们的boolean active属性进行匹配,如果categorizedBooks books数组中的一个对象为空,我想将其删除。

因此,在这种情况下,我会得到这样的信息(上述期望的输出):

{
 name: "category1",
 books:[
        {name:"book1", bookContainerId: 1, active: true}
       ]
 },
{
 name: "category2",
 books:[
        {name:"book4", bookContainerId: 1, active: false},
        {name:"book5", bookContainerId: 3, active: true}
       ]
 },
{
 name: "category3",
 books:[
        {name:"book7", bookContainerId: 1, active: false}
       ]
 }

另一个问题是,我不想修改原始数组,因为我希望能够使用新数组来调用它,以便在任何时候进行过滤并获得结果。现在是我的GET方法:

public get bookCategories(): Array<CategorizedBook> {
    let cloneToMapOf = [...this.categoriesAndBooks];

    const filteredCategories = cloneToMapOf.map(categorizedbooks => {
        categorizedbooks.books = categorizedbooks.properties.filter(book =>{
            return (rc.includes(books.bookContainerId) && 
sa.includes(book.active ? 'active' : 'inactive'));
        });
        return categorizedbooks;
    });

    const result = filteredCategories.filter(x => x.books.length > 0 && x.books != null);
    return result;
}

但是由于某种原因,此代码修改了this.categoriesAndBooks,所以我在一段时间后变得空了。。

我想在HTML中显示结果

    <nz-collapse [nzBordered]="false" *ngFor="let categorizedBook of bookCategories;">
        <nz-collapse-panel [nzHeader]="categorizedBook.name" [nzActive]="true">
            <ng-container *ngFor="let book of categorizedBook.properties; trackBy:trackBy.book">
                <ng-template [ngTemplateOutlet]="bookEditors" [ngTemplateOutletContext]="{book: book, form: bookValueForm}"></ng-template>
            </ng-container>
        </nz-collapse-panel>
    </nz-collapse>

我已经坐了几个小时了。请帮助我

javascript arrays typescript filter
2个回答
0
投票

您可以将所需的键放在数组中并添加值,而不是添加一些需要转换为对象的数据类型以进行测试的语义值。

结果是一个具有过滤后的子数组的数组,如果子数组包含某些元素,则将其重新组合。

var categorizedBooks = [{ name: "category1", books: [{ name: "book1", bookContainerId: 1, active: true }, { name: "book2", bookContainerId: 2, active: false }, { name: "book3", bookContainerId: 2, active: true }] }, { name: "category2", books: [{ name: "book4", bookContainerId: 1, active: false }, { name: "book5", bookContainerId: 3, active: true }, { name: "book6", bookContainerId: 4, active: true }] }, { name: "category3", books: [{ name: "book7", bookContainerId: 1, active: false }, { name: "book8", bookContainerId: 2, active: true }, { name: "book9", bookContainerId: 4, active: false }] }, { name: "category4", books: [{ name: "book10", bookContainerId: 2, active: false }, { name: "book11", bookContainerId: 2, active: false }, { name: "book12", bookContainerId: 4, active: false }] }],
    filters = [['bookContainerId', [1, 3]], ['active', [true, false]]],
    result = categorizedBooks.reduce((r, { name, books }) => {
        books = books.filter(o => filters.every(([k, v]) => v.includes(o[k])));
        if (books.length) r.push({ name, books });
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

0
投票

更新

const filteredCategories = cloneToMapOf.map(categorizedbooks => {
        const books = categorizedbooks.properties.filter(book =>{
            return (rc.includes(books.bookContainerId) && 
sa.includes(book.active ? 'active' : 'inactive'));
        });
        return {...categorizedbooks,books}; // so that original array is not mutated.
    });

我为属于容器一部分的书创建了一个内部过滤器,并且活动状态是活动数组中的状态之一,然后为具有空书本数组的类别创建了一个外部过滤器

var categorizedBooks = [
{
 name: "category1",
 books:[
        {name:"book1", bookContainerId: 1, active: true},
        {name:"book2", bookContainerId: 2, active: false},
        {name:"book3", bookContainerId: 2, active: true},
       ]
 },
{
 name: "category2",
 books:[
        {name:"book4", bookContainerId: 1, active: false},
        {name:"book5", bookContainerId: 3, active: true},
        {name:"book6", bookContainerId: 4, active: true},
       ]
 },
{
 name: "category3",
 books:[
        {name:"book7", bookContainerId: 1, active: false},
        {name:"book8", bookContainerId: 2, active: true},
        {name:"book9", bookContainerId: 4, active: false},
       ]
 },
{
 name: "category4",
 books:[
        {name:"book10", bookContainerId: 2, active: false},
        {name:"book11", bookContainerId: 2, active: false},
        {name:"book12", bookContainerId: 4, active: false},
       ]
 }
 ];
var bookContainers = [1,3]
var isActive = ['active', 'inactive'];

var isActiveBoolState = isActive.map(state => state === 'active'); // helper to show which type of active state should be showed.

var result = categorizedBooks.map(category => ({...category, books: category.books.filter(book => bookContainers.includes( book.bookContainerId) && isActiveBoolState.includes(book.active)  )})).filter(category => category.books.length);

console.log(result);
© www.soinside.com 2019 - 2024. All rights reserved.