0

How do I get a new array from a specific array?

I don't known how to handle an Array like this:

let arr1 = [
  {name: 'a', age: 1},
  {name: 'a', age: 2},
  {name: 'a', age: 3},
  {name: 'b', age: 1},
  {name: 'b', age: 2}
  {name: 'b', age: 3}
  {name: 'c', age: 1}
  {name: 'c', age: 2}
  ...
]

"I want this result: from each item with the same name, pick biggest age value"

let arr2 = [
  {name: 'a', age: 3},
  {name: 'b', age: 3},
  {name: 'c', age: 2} 
  ...
]
SherylHohman
  • 16,580
  • 17
  • 88
  • 94
EVDS
  • 13
  • 2
  • 1
    `const arr2 = arr1.filter( a => a.age === Math.max( ...arr1.filter( b => b.name === a.name ).map( ({ age }) => age ) ) );` – Paul Jul 01 '19 at 23:47
  • I think that's what you want, but I'm on mobile so I can't post an answer with code easily. – Paul Jul 01 '19 at 23:48

6 Answers6

3

Just use filter to select all items with the highest age for their name.

let arr1 = [{name:'a',age:1},{name:'a',age:2},{name:'a',age:3},{name:'b',age:1},{name:'b',age:2},{name:'b',age:3}];

const biggest = arr1.reduce((a, { name, age }) => {
  a[name] = a[name] || age;
  age > a[name] ? a[name] = age : a[name];
  return a;
}, {});

let arr2 = arr1.filter(({ name, age }) => biggest[name] == age);

console.log(arr2);
.as-console-wrapper { max-height: 100% !important; top: auto; }
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
2

You can use a combination of reduce and Object.values

 const arr1 = [
  {name: 'a', age: 1},
  {name: 'a', age: 2},
  {name: 'a', age: 3},
  {name: 'b', age: 1},
  {name: 'b', age: 2},
  {name: 'b', age: 3},
  {name: 'c', age: 1},
  {name: 'c', age: 2},
]

const maxNames = arr1.reduce((maxNamesObject, item) => {
  const { name, age } = item
  const maxItem = maxNamesObject[name]
  if (!maxItem || age > maxItem.age) {
    maxNamesObject[name] = item
  }
  return maxNamesObject
}, {})

const output = Object.values(maxNames)

console.log(output)
Zaytri
  • 2,582
  • 2
  • 13
  • 19
0

Extracted from this answer: How to filter object array based on attributes?

You can use the Array.prototype.filter method:

let arr2 = arr1.filter(function (obj) {
  return obj.age === 3;
});
Ben Carey
  • 16,540
  • 19
  • 87
  • 169
0

This is a more beautiful solution:

let arr1 = [
  {name: 'a', age: 1},
  {name: 'a', age: 2},
  {name: 'a', age: 3},
  {name: 'b', age: 1},
  {name: 'b', age: 2},
  {name: 'b', age: 3},
  {name: 'c', age: 1},
  {name: 'c', age: 2},
]

arr2 = Array.from(new Set(arr1.map(e => e.name))).map(e => { 
    return {
        name: e,
        age: Math.max(...arr1.filter(ee => ee.name == e).map(ee => ee.age))
    }
})

console.log(arr2)

Blockquote

Artee
  • 824
  • 9
  • 19
0

my solution:

const arr1 = [
  {name: 'a', age: 1},
  {name: 'a', age: 2},
  {name: 'a', age: 3},
  {name: 'b', age: 1},
  {name: 'b', age: 2},
  {name: 'b', age: 3},
  {name: 'c', age: 1},
  {name: 'c', age: 2},
]

let arr2 = arr1.reduce((acc, item) => {      
  let objectExists = acc.find(e => e.name === item.name)
  if (!objectExists) acc.push(item)
  else if (objectExists.age < item.age) {
      acc[acc.indexOf(objectExists)].age = item.age
  }
  return acc
}, [])

console.log(arr2)
Christian Carrillo
  • 2,751
  • 2
  • 9
  • 15
-1

I didn't notice you update the question. This is not the most pro code.

  let arr1 = [
  {name: 'a', age: 1}, {name: 'a', age: 2}, {name: 'a', age: 3},
  {name: 'b', age: 1}, {name: 'b', age: 2}, {name: 'b', age: 3},
  {name: 'c', age: 1}, {name: 'c', age: 2} ];

  let names = [];
  let output = [];

  for(obj of arr1){
   if (!names.includes(obj.name)) names.push(obj.name);
  }

  for(obj of names){
    let current = arr1.filter(x => x.name === obj)
                      .reduce((a,b) => a.age > b.age ? a : b);

    output.push(current);
  }

    console.log(output);
Alejandro
  • 104
  • 4