【问题标题】:Filter JavaScript array based on object property from another array根据来自另一个数组的对象属性过滤 JavaScript 数组
【发布时间】:2019-10-17 05:21:58
【问题描述】:

我在 JavaScript 中有 2 个数组。其中一个需要根据另一个的属性进行过滤。

我有一个像这样的电影列表:

[
  {
    id: 1,
    type: 'movies',
    attributes: {
      name: 'Batman'
    }
  },
  {
    id: 2,
    type: 'movies',
    attributes: {
      name: 'Spiderman'
    }
  },
  ...
]

然后我有另一个数组,其中包含用户观看过的电影,但它们位于数组内的嵌套对象中,作为遵循 JSON API 规范的关系。

[
  {
    id: '1',
    type: 'moviesWatched',
    attributes: {
      comment: 'Excellent film, would recommend to anyone who loves a action film!'
    },
    relationships: {
      movie: {
        data: {
           type: 'movies',
           id: 2
        }
      }
    }
  }
]

我需要实现的是我需要将来自watchList[].relationships.movie.data.id 的 id 与第一个数组交叉引用。显然,这个列表在生产中要长得多,但我希望实现的是拥有用户观看的电影的完整列表,其中电影的名称基于 2 个这样格式化的数组,以节省我不必存储不必要的数据库内部的数据。

数组的结果将类似于...

[
  {
    id: 1,
    type: 'movies',
    attributes: {
       name: 'Batman'
    },
    meta: {
      watched: false
    }
  },
  {
    id: 2,
    type: 'movies',
    attributes: {
      name: 'Spiderman'
    },
    meta: {
      watched: true
    }
  }
]

这是我目前所拥有的,它正在工作,但我不知道是否有更好的方法来解决它......

movies.map((movie) => {
    const watched = watchedMovies.find((searchable) => {
        return searchable.relationships.movie.data.id === searchable.id;
    });

    movie.meta.watched = watched || false;

    return movie;
});

【问题讨论】:

  • 您的问题不清楚。你似乎没有过滤任何东西;对于第一个数组中的每部电影,您只需将附加属性 meta.watched 设置为 true 或 false。另外,您自己尝试过什么?
  • @slider 编辑了问题以获得我目前编码的内容

标签: javascript arrays


【解决方案1】:

既然您说列表可能很长,您可以将“观看”的电影 id 提取到 Set,然后根据电影的 id 是否在集合中来设置电影的 meta.watched 属性:

const movies = [{
    id: 1,
    type: 'movies',
    attributes: {
      name: 'Batman'
    }
  },
  {
    id: 2,
    type: 'movies',
    attributes: {
      name: 'Spiderman'
    }
  }
];

const watched = [{
  id: '1',
  type: 'moviesWatched',
  attributes: {
    comment: 'Excellent film, would recommend to anyone who loves a action film!'
  },
  relationships: {
    movie: {
      data: {
        type: 'movies',
        id: 2
      }
    }
  }
}];

const watchedSet = new Set(watched.map(m => m.relationships.movie.data.id));
movies.forEach(movie => movie.meta = {watched: watchedSet.has(movie.id)});

console.log(movies);

【讨论】:

  • 很好的答案,我已经有一段时间没有看到 new Set() 这么好的用例了
  • 纯粹出于我自己的好奇,在这里使用 Set 而不是普通数组和 indexOf 有什么好处?我知道 Set 只有唯一值,但根据问题和数据结构,看起来同一个电影 ID 不会出现在多个 moviesWatched 条目中。也许我错过了一些东西。不错的答案,否则,赞成。
  • @Andy Set 数据结构允许我们以恒定时间(与使用普通数组和indexOf 的线性时间相反)测试值是否在其中(使用has) .虽然在 EcmaScript 规范中不保证这种恒定时间访问,但在大多数实现(例如 V8、Firefox)中它是恒定时间。因此,上面带有集合的代码的时间复杂度将是O(n)。但是使用数组和indexOf,它将是O(mn)。
猜你喜欢
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-19
  • 1970-01-01
  • 2019-09-15
  • 2020-01-10
  • 2019-02-23
  • 1970-01-01
相关资源
最近更新 更多