2016-12-01 79 views
1

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

{ 
"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() 
+0

我的坏,它应该是图像1和图像2 – user3642173

+0

说实话,你可能甚至不需要任何特殊的观察到魔术这个......你的'map'功能正好可以将对象从API和将其减少到该阵列中。所有的逻辑都可以在'map'回调中进行。 Observable自己的操作符更是*操纵数据流,而不是流*中的数据。细微的差异,但重要。这就是为什么我认为这是在'map'的回调之内,你可以简单地处理数据。你不需要“独特”排放,你需要改变实际数据。 – aaronofleonard

+0

请提高问题的质量,澄清可观察的'this.af.database.list('/ photos/user')'的结构。定义类型和成员。 –

回答

2

UPDATE

我在原始答案中假定它是一个包含单个项目的流。后来的OP澄清它是一个照片列表的流。在这种情况下,我们使用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在一个流中可观察到的回报独特的个体价值,而不是我们在这里想要的操作。有可能产生一个包含所有标签的序列,每个标签都是一个独立的值,但是我们需要重新对它们进行重新组合。我们可以使用reduce,与数组相对应。它需要一个初始值([])并累计其他值。我们在每次迭代中建立了一个包含各个值的列表。减少后我们有一个独特的标签数组。

请注意,.list()应该完成可观察的工作。

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)) 
     }, []) 
+0

谢谢你。它看起来像一个很好的解决方案,但不幸的是它不起作用。 1)我得到一个错误,**属性包含“不存在于'类型'任何[] **。另外,当我订阅结果时,我没有得到任何输出。我应该如何确保.list()完成后才能正常工作? – user3642173

+1

re:'includes',它来自ES2016,将'lib:[“es2016”]'添加到'tsconfig.json'。你可能需要一个polyfill。我想我会改变使用indexOf() –

+0

我看到的答案,至于.list()大部分应该完成,我应该调用。()之前调用类似take(x)? – user3642173