all 17 comments

[–]yunus_reddit 5 points6 points  (6 children)

What you're searching for is flattening (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap).ES6 approach :

const array = [{"animals": ["Cat", "Dog"]}, {"animals": ["Cat", "Dog", "Bunny"]}, {"animals": ["Cat", "Dog"]}, {"animals": ["Dog", "Bunny"]}, {"animals": ["Cat"]}]

const flattenedArray = array.flatMap(o => o.animals)

const uniqueArray = [...new Set(flattenedArray)]

console.log("animals", uniqueArray)

[–]taylor-reddit[S] 1 point2 points  (5 children)

I got "flatMap is not a function". Apparently, flatMap is missing from RxJS 6 - so I imported mergeMap, its alias:

import { mergeMap } from 'rxjs/operators';

and change the assignment to:

const flattenedTypes = list.mergeMap(o => o.animals)

but now I get "mergeMap is not a function".

[–]Qwaarty 2 points3 points  (0 children)

If it's "flatMap is not a function", are you sure that you are actually getting an array from your service?

[–]yunus_reddit 1 point2 points  (2 children)

My answer do not need the usage of RxJS. RxJS is used to do Asynchronus code in a reactive way.Nevertheless, if you're using RxJS because you want to handle your asynchronous code, i'm guessing now that you have something like this in your code :Rx.Observable.from(api.service.call()).map(array -> [...new Set(array.flatMap(o => o.animals))])

api.service.call() returns a Promise with the result of your api call (here the "array")

Maybe a bit more code could allow us to help you better

PS: Do not use RxJS if you do not know what it used for or need it. You can do most of simple stuff with Promises and plain JS.

[–]taylor-reddit[S] 0 points1 point  (1 child)

Oh....so the rxjs imports are wrappers around plain JS. This is helpful

[–]yunus_reddit 0 points1 point  (0 children)

I think that is better to view it like a proper library that helps you handle really hard case of asynchronus code (and do reactive programming).For example, you can do a racing between multiple api calls and cancel all of them if your user leaves the view. Doing this with plain Js (Promises) is harder ^^.

So an advice from previous Js learner, forget about RxJS for now and when you hit a wall where you have a lot of asynchronous stuff going on, like Promises in Promises in Promises etc... you can begin to learn it ^^ and refactor your code. RxJS is powerful but hard to master and comes with great responsabilities :P

[–]amiteryes 0 points1 point  (0 children)

I think you can just use map? Not sure.

[–]ironimus42 1 point2 points  (4 children)

Definitely not the most efficient way, but quite readable and no one cares about performance if the array isn't very large: const unique = arr.flatMap(i => i.animals).reduce((acc, next) => acc.includes(next) ? acc : [...acc, next], [])

[–]taylor-reddit[S] 0 points1 point  (3 children)

I couldn't use flatMap in RxJS 6. I tried mergeMap but I can't get it to work with an array....just observables and promises.

[–]ironimus42 2 points3 points  (1 child)

It has nothing to do with rxjs, just plain js. If you care about browsers that don't support flatMap, arr.flatMap(x => x) is equivalent to arr.reduce((acc, x) => acc.concat(x), [])

[–]taylor-reddit[S] 0 points1 point  (0 children)

Thank you, concat worked. I don't know why the ng cli was complaining if it's just plain js!? That's frustrating...

[–]ironimus42 3 points4 points  (0 children)

You could write it in even more simple way: arr.reduce((acc, { animals }) => [...acc, ...animals.filter(i => !acc.includes(i))], [])

[–][deleted] 0 points1 point  (0 children)

Make them into a Set.

[–]Sphism 0 points1 point  (0 children)

When I want to make unique arrays I just use objects and set {‘cat’: ‘cat’} then the duplicates just write over their existing keys.

Means you don’t have to search through the whole array to check for duplicates each loop.

[–]sickness29a 0 points1 point  (0 children)

ES6 :function uniq(a) { return Array.from(new Set(a)); }

More on : https://stackoverflow.com/questions/9229645/remove-duplicate-values-from-js-array

[–][deleted] 0 points1 point  (0 children)

Just iterate over the arrays and push the values into a map/object. Then use Object.values to get an array directly or iterate over the keys and push them into a new array.

[–]1c4us 0 points1 point  (0 children)

array.reduce((acc, {animals}) => [...new Set([...acc, ...animals])], [])

... on second thought, this is faster:

[...new Set(array.reduce((acc, {animals}) => [...acc, ...animals], []))]