过滤对象数组中的数组

时间:2019-10-09 19:36:29

标签: javascript arrays typescript filter

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

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>

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

2 个答案:

答案 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);

答案 1 :(得分: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; }