简体   繁体   中英

Filter List of Object-Nested Objects with Object Containing Key-Array Pair

I tried to came up with the most descriptive title.

I came up with a solution but its terribly inefficient as its in the order of O(n^4) or so, which is pathetic.

I am trying to filter and return a list of objects based on a filter-object and matching key values.

I will have a list of movies, movieList , and I will return all movies that meet all the key-value pairs that are contained within the movieFilter object. In the case of genre , the movie must be one of the genres. Since sales is not in the filter we do not filter based on it.

let movieFilter = {
  "genre": ["Action", "Romance"],
  "director": "Bob",
  "writer": ["Jim", "Dave", "Alice"],
  "duration": "2"
}

let movie = {
  "genre" : "Action",
  "people": {
    "director": "Bob",
    "writer": "Alice"   
  }
  "boxoffice": "9,000,000",
  "duration": "2"
}

let movies = [{
  "genre" : "Action",
  "people": {
    "director": "Bob",
    "writer": "Alice"   
  }
  "boxoffice": "9,000,000",
  "duration": "2"
}, 
{
  "genre" : "Comedy",
  "people": {
    "director": "Rose",
    "writer": "Mike"   
  }
  "boxoffice": "12,000,000",
  "duration": "3"
}]

The issue I'm having is that because some filters (like the genre filter) are in arrays and some movie keys (like people ) are nested within an object I am forced to nest loops within loops, which makes the time complexity grow.

I could change the way the filter is structures, but the way it currently is makes sense to me. The movie object format is something I cannot change.

Any suggestion on how I could tackle this would be appreciated.

It can be done using filter method and some method:

 let movieFilter = { "genre": ["Action", "Romance"], "director": "Bob", "writer": ["Jim", "Dave", "Alice"], "duration": "2" } let movies = [ { "genre": "Action", "people": { "director": "Bob", "writer": "Alice" }, "boxoffice": "9,000,000", "duration": "2" }, { "genre": "Comedy", "people": { "director": "Rose", "writer": "Mike" }, "boxoffice": "12,000,000", "duration": "3" }] const result = movies.filter(f => movieFilter.genre.some(ge=> ge == f.genre) && movieFilter.director == f.people.director && movieFilter.writer.some(wr => wr == f.people.writer) && movieFilter.duration == f.duration ); console.log(result);

UPDATE:

Thanks to @MkeSpaGuy comment. I've remade a little bit approach to filter your items.

It is slightly optimized version using key to check whether filter conditions are satisfied:

 let movieFilter = { "genre": ["Action", "Romance"], "director": "Bob", "writer": ["Jim", "Dave", "Alice"], "duration": "2" } movieFilter.genre = movieFilter.genre.reduce((a, key) => ({...a, [key]: 1}), {}); movieFilter.writer = movieFilter.writer.reduce((a, key) => ({...a, [key]: 1}), {}); let movies = [{ "genre": "Action", "people": { "director": "Bob", "writer": "Alice" }, "boxoffice": "9,000,000", "duration": "2" }, { "genre": "Comedy", "people": { "director": "Rose", "writer": "Mike" }, "boxoffice": "12,000,000", "duration": "3" }]; const result = movies.filter(f => movieFilter.genre[f.genre] && movieFilter.director == f.people.director && movieFilter.writer[f.people.writer] && movieFilter.duration == f.duration ); console.log(result);

Consider replacing your arrays with objects inside your movieFilter.

 let movieFilter = { genre: { Action: true, Romance: true }, director: "Bob", writer: { Jim: true, Dave: true, Alice: true }, duration: "2" }; let movies = [ { genre: "Action", people: { director: "Bob", writer: "Alice" }, boxoffice: "9,000,000", duration: "2" }, { genre: "Comedy", people: { director: "Rose", writer: "Mike" }, boxoffice: "12,000,000", duration: "3" } ]; const filterOnMovieFilter = movie => { const { genre, people, duration } = movie; const { writer, director } = people || {}; return ( movieFilter.genre[genre] && movieFilter.writer[writer] && movieFilter.duration === duration && movieFilter.director === director ); }; console.log(movies.filter(filterOnMovieFilter));

However, please avoid premature optimization . You will not notice optimization when filtering 10,000 items in a modern browser.
(Notice I said filter and not display) I often do things that are less efficient in favor of simple, concise, immutable, readable and useful code. If you are targeting a feature phone or find a real performance bottleneck, you will need to measure with performance monitoring tools. The JavaScript engine optimizations are continuously improving and results are often surprising.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM