-1

I have a structure similar to this (only test data, so typos are irrelevant):

 "People" :  [
      {
        "name": "Bob",
        "animals" : [{
          "name" : "Scott",
          "type" : "Cat"
        },
        {
          "name" : "Eva",
          "type" : "Cat"
        }
        {
          "name" : "Sven",
          "type" : "Dog"
        }]
      },
      {
        "name": "Bob",
        "animals" : [{
          "name" : "Chris",
          "type" : "Dog"
        },
        {
          "name" : "Greg",
          "type" : "Cat"
        },
        {
          "name" : "Ior",
          "type" : "Horse"
        }]
      }
    ]

Basically what I want to do is to get all unique animal types from this collection. My problem is mapping into two arrays (People : [], Animals : []). The question:

How do I .map all the "type" attributes to get a new unique collection? like:

["Cat", "Dog", "Horse"]

Will update if I get an example done using C# LINQ.

JakobMillah
  • 261
  • 4
  • 17
  • Please visit the [help], take the [tour] to see what and [ask]. Do some research, search for related topics on SO; if you get stuck, post a [mcve] of your attempt, noting input and expected output. – mplungjan Apr 18 '18 at 09:11
  • Hint : `reduce`, `map`, `concat` and finally to `Set` to `Array`. – gurvinder372 Apr 18 '18 at 09:14
  • @gurvinder372 will look into reduce and concat and see if it's of use here... Familiar with Set. – JakobMillah Apr 18 '18 at 09:16

5 Answers5

1
let _animals = {}
People.forEach(person => {
  person.animals.forEach(animal => {
     _animals[animal.name] = true 
  })
})
let result = Object.keys(_animals)

Enhanced with more es6:

let _animals = {}
People.forEach(({animals}) =>
    animals.forEach(({name}) =>
    _animals[name] = true 
  )
)
let result = Object.keys(animals)
challenger
  • 2,056
  • 1
  • 14
  • 23
  • 1
    This was a great way of doing it. Will have to look into use cases for `.forEach` in javascript as I've kind of settled with `.filter`, `.map` and `.find`. Thank you – JakobMillah Apr 18 '18 at 09:27
0

See Set and Array.prototype.forEach() for more info on animalsFrom().

See Array.prototype.map() and Flattening Arrays for more info on the latter method (listAnimals()).

// Input.
const input = {"people":  [{"name": "Bob","animals": [{"name": "Scott","type": "Cat"},{"name" : "Eva","type": "Cat"},{"name" : "Sven","type": "Dog"}]},{"name": "Bob","animals": [{"name" : "Chris","type" : "Dog"},{"name": "Greg","type": "Cat"},{"name": "Ior","type": "Horse"}]}]}

// Animals From.
const animalsFrom = ({people}) => {
  
  const animals = new Set()
  
  people.forEach(person => {
    person.animals.forEach(animal => animals.add(animal.type))
  }) 

  return [...animals.values()]
}

// List Animals (Advanced).
const listAnimals = ({people}) => [...new Set([].concat.apply([], people.map(({animals}) => animals.map(({type}) => type))))]

// Proof.
console.log('Animals From', animalsFrom(input))
console.log('List Animals', listAnimals(input))
Arman Charan
  • 4,717
  • 2
  • 18
  • 26
0
var unique = {};   // Create an associative array 
for (j = 0; j < People.length; j++) { // Iterate through Parents
    for(i = 0; i < People[j].animals.length; i++) { // Iterate through animals
        var node = unique[People[j].animals[i].type] = unique[People[j].animals[i].type] || {}; 
        // Here unique is built. If there is no entry with the current type as the id, a new entry in unique will be added. 
    }
}
Stephan T.
  • 4,914
  • 3
  • 15
  • 32
0

ES6

You can use reduce(), new Set([]) and the spread operator to get the required result.

DEMO

const arr = [{
    "name": "Bob",
    "animals": [{
        "name": "Scott",
        "type": "Cat"
    }, {
        "name": "Eva",
        "type": "Cat"
    }, {
        "name": "Sven",
        "type": "Dog"
    }]
}, {
    "name": "Bob",
    "animals": [{
        "name": "Chris",
        "type": "Dog"
    }, {
        "name": "Greg",
        "type": "Cat"
    }, {
        "name": "Ior",
        "type": "Horse"
    }]
}];

let result = arr.reduce((r, {animals}) =>[...r,...animals.map(({type})=>type)], []);


console.log([ ...new Set(result)]);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Community
  • 1
  • 1
Narendra Jadhav
  • 8,799
  • 15
  • 28
  • 38
0

Use reduce, map, concat and finally to Set to Array as shown below

var output = [...new Set( arr.reduce( (a,c) => a.concat( c.animals.map( s => s.type )) , []))]

Explanation

  • Use reduce to iterate array (people) to get all values for animals type
  • Use map to iterate animals and return their types, and concatenate result of map to accumulator a
  • Use Set to remove duplicates.
  • Use spread operator ... to convert back to Array.

Demo

var arr = [{
    "name": "Bob",
    "animals": [{
        "name": "Scott",
        "type": "Cat"
      },
      {
        "name": "Eva",
        "type": "Cat"
      },
      {
        "name": "Sven",
        "type": "Dog"
      }
    ]
  },
  {
    "name": "Bob",
    "animals": [{
        "name": "Chris",
        "type": "Dog"
      },
      {
        "name": "Greg",
        "type": "Cat"
      },
      {
        "name": "Ior",
        "type": "Horse"
      }
    ]
  }
];
var output = [...new Set(arr.reduce((a, c) => a.concat(c.animals.map(s => s.type)), []))];
console.log(output);
gurvinder372
  • 61,170
  • 7
  • 61
  • 75