在Angular2中展平可观察数组

时间:2016-12-01 18:52:04

标签: javascript angular firebase firebase-realtime-database observable

我在Angular2应用中使用Firebase从我的数据库中检索数据。在嵌套的标记列表中返回一组唯一值最简单的方法是什么?即在我的示例中,我想返回["Sport", "Adventure", "Music"],其中第二个"冒险" 被省略。

{
"images": {
    "image1": {
        "path": "path",
        "date": 43534532123,
        "tags": {
           0: "Sport",
           1: "Adventure"
        }
    },
    "image2": {
        "path": "path",
        "date": 43534532123,
        "tags": {
           0: "Music",
           1: "Adventure"
        }
     }            

 }

我尝试过这种方法,但它似乎只从第一张图片中拆分了元素

 return this.af.database.list('/photos/user')
      .map(photos => photos.map(photo => photo.tags))
      .concatAll()
      .distinct()

然而,这种方法产生正确的输出,但作为独特标记的单独流而不是作为一个数组

 return this.af.database.list('/photos/user')
      .map(photos => photos.map(photo => photo.tags))
      .mergeAll()
      .mergeAll()
      .distinct()

1 个答案:

答案 0 :(得分:2)

<强>更新

我在原始答案中假设它是一个包含各个项目的流。后来,OP澄清了它是 photos 列表的流。在这种情况下,我们使用Array#reduce代替Observable#reduce

return this.af.database.list('/photos/user')
  .map(photos => photos.map(photo => photo.tags)
      .reduce((allTags, current) => {
           return allTags.concat(
               current.filter(item => allTags.indexOf(item) === -1))
      }, []))

原始回答

distinct对一个observable返回一个流中唯一的单个值,但不是我们想要的运算符。可以生成一个包含所有标签的序列,每个标签都作为一个单独的值,但是我们需要重新组合它们。

我们可以使用reduce,非常类似于Array对应物。它采用初始值([])并累积其他值。我们在每次迭代中构建了一个包含各个值的列表。在reduce之后,我们有一系列独特的标签。

请注意.list()应该完成observable才能工作。

return this.af.database.list('/photos/user')
      .map(photos => photos.map(photo => photo.tags))
      .reduce((allTags, current) => {
           return allTags.concat(
               current.filter(item => allTags.indexOf(item) === -1))
      }, [])