Kivo
Kivo

Reputation: 435

Filter inside a nested array with objects

I have an array that contains three book objects. Each book object has an array of bookIds . I want to filter by bookId (3,1) in a fast and efficient way since my array will grow up easly in the future. I tried with map, but it change my original array even with a deepCopy ! Is there a way to use the filter function instead without using recursivity ?

this.booksList = 
    [
      {
        "books": [
          {
            "bookId": 3
          },
          {
            "bookId": 2
          }
        ],
        "id": 1,
        "name": "Name 1",
        "description": "desc 1"
      },
      {
        "books": [
          {
            "bookId": 5
          },
          {
            "bookId": 2
          }
         ],
         "id": 2,
         "name": "Name 2",
         "description": "desc 2"
      },
      {
        "books": [
          {
            "bookId": 1
          },
          {
            "bookId": 3
          }
         ],
         "id": 3,
         "name": "Name 3",
         "description": "desc 3"
      }
    ]

The map approach :

let results = this.books.map(function (book) {
            book.books = book.books.filter(x => x.bookId == 1 || x.bookId == 3);
            return book;
        }).filter(({ books }) => books.length);

Result with map : not expected result !

[
  {
    "books": [
      {
        "bookId": 3
      }
    ],
    "id": 1,
    "name": "Name 1",
    "description": "desc 1"
  },
  {
    "books": [
      {
        "bookId": 1
      },
      {
        "bookId": 3
      }
     ],
     "id": 3,
     "name": "Name 3",
     "description": "desc 3"
  }
]

expected results :

[
  {
    "books": [
      {
        "bookId": 3
      },
      {
        "bookId": 2
      }
    ],
    "id": 1,
    "name": "Name 1",
    "description": "desc 1"
  },
  {
    "books": [
      {
        "bookId": 1
      },
      {
        "bookId": 3
      }
     ],
     "id": 3,
     "name": "Name 3",
     "description": "desc 3"
  }
]

Thanks,

Upvotes: 0

Views: 67

Answers (2)

Roko C. Buljan
Roko C. Buljan

Reputation: 206593

const booksList=[
  {books:[{bookId:3},{bookId:2}],id:1,name:"Name 1",description:"desc 1"},
  {books:[{bookId:5},{bookId:2}],id:2,name:"Name 2",description:"desc 2"},
  {books:[{bookId:1},{bookId:3}],id:3,name:"Name 3",description:"desc 3"},
];

const byBookIDs = (...IDs) =>
  booksList.filter(b => b.books.some(b => IDs.includes(b.bookId)));

console.log(byBookIDs(1, 3));

Upvotes: 0

Mulan
Mulan

Reputation: 135416

I think you are looking for filter and some -

const input =
  [{books:[{bookId:3},{bookId:2}],id:1,name:"Name 1",description:"desc 1"},{books:[{bookId:5},{bookId:2}],id:2,name:"Name 2",description:"desc 2"},{books:[{bookId:1},{bookId:3}],id:3,name:"Name 3",description:"desc 3"}]

const query =
  [3, 1]

const result =
  input.filter(({ books = [] }) =>
    books.some(({ bookId = null }) => query.includes(bookId))
  )

console.log(JSON.stringify(result, null, 2))

Output -

[
  {
    "books": [
      {
        "bookId": 3
      },
      {
        "bookId": 2
      }
    ],
    "id": 1,
    "name": "Name 1",
    "description": "desc 1"
  },
  {
    "books": [
      {
        "bookId": 1
      },
      {
        "bookId": 3
      }
    ],
    "id": 3,
    "name": "Name 3",
    "description": "desc 3"
  }
]

Upvotes: 2

Related Questions