Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find all unique values for specific key in array of objects in Javascript?

I have an array of javascript objects and I am trying to get an array of all unique values for a specific property in each object. I tried to do this using reduce(), my example code is below, but it results in an error that it "Cannot read properties of undefined (reading 'includes')" even though I provided an initial value of an empty array. The intended result is an array with

['New York', 'San Francisco', 'Chicago', 'Los Angeles']

The end goal is to create a bar graph with the cities on the X-axis and the calculated average wage for each city on the Y-axis, so I need the unique list of cities. Is there a way to avoid this error, or a better way to do this altogether?

const employees= [
 {id: 0, city: 'New York', wagePerHour: '15'}, 
 {id: 1, city: 'San Francisco', wagePerHour: '18'}, 
 {id: 2, city: 'New York', wagePerHour: '16'}, 
 {id: 3, city: 'Chicago', wagePerHour: '14'}, 
 {id: 4, city: 'Chicago', wagePerHour: '12'}, 
 {id: 5, city: 'San Francisco', wagePerHour: '15'}, 
 {id: 6, city: 'New York', wagePerHour: '18'}, 
 {id: 7, city: 'Los Angeles', wagePerHour: '10'}
];
const cities = employees.reduce((foundValues, nextEmployee) => {
 if(! foundValues.includes(nextEmployee.city)) {
  foundValues.push(nextEmployee.city);
 }
}, []);
like image 266
Sarah Avatar asked Oct 30 '25 17:10

Sarah


2 Answers

An even simpler way would be to extract all the cities names and use the Set function to build a unique array:

const employees = [{ id: 0, city: 'New York', wagePerHour: '15' }, { id: 1, city: 'San Francisco', wagePerHour: '18' }, { id: 2, city: 'New York', wagePerHour: '16' }, { id: 3, city: 'Chicago', wagePerHour: '14' }, {  id: 4, city: 'Chicago', wagePerHour: '12' }, { id: 5, city: 'San Francisco', wagePerHour: '15' }, {  id: 6, city: 'New York', wagePerHour: '18' }, { id: 7, city: 'Los Angeles', wagePerHour: '10' }]

let cities = [... new Set(employees.map(x=>x.city))];

console.log(cities);
like image 91
Pellay Avatar answered Nov 02 '25 09:11

Pellay


With Array#reduce you have to return the updated previousValue. The easiest way to fix your code is to add return foundValues, which you could re-write as:

const cities = employees.reduce((foundValues, nextEmployee) => 
    foundValues.includes(nextEmployee.city) ? 
    foundValues : foundValues.concat(nextEmployee.city), []
);

However, you're free to explore other more efficient approaches, especially with the use of Array#map and [...new Set()]

const employees= [
 {id: 0, city: 'New York', wagePerHour: '15'}, 
 {id: 1, city: 'San Francisco', wagePerHour: '18'}, 
 {id: 2, city: 'New York', wagePerHour: '16'}, 
 {id: 3, city: 'Chicago', wagePerHour: '14'}, 
 {id: 4, city: 'Chicago', wagePerHour: '12'}, 
 {id: 5, city: 'San Francisco', wagePerHour: '15'}, 
 {id: 6, city: 'New York', wagePerHour: '18'}, 
 {id: 7, city: 'Los Angeles', wagePerHour: '10'}
];
const cities = employees.reduce((foundValues, nextEmployee) => {
   if(!foundValues.includes(nextEmployee.city)) {
      foundValues.push(nextEmployee.city);
   }
   return foundValues;
}, []);

console.log( cities );

rewrite

const employees= [
 {id: 0, city: 'New York', wagePerHour: '15'}, 
 {id: 1, city: 'San Francisco', wagePerHour: '18'}, 
 {id: 2, city: 'New York', wagePerHour: '16'}, 
 {id: 3, city: 'Chicago', wagePerHour: '14'}, 
 {id: 4, city: 'Chicago', wagePerHour: '12'}, 
 {id: 5, city: 'San Francisco', wagePerHour: '15'}, 
 {id: 6, city: 'New York', wagePerHour: '18'}, 
 {id: 7, city: 'Los Angeles', wagePerHour: '10'}
];
const cities = employees.reduce((foundValues, nextEmployee) => 
    foundValues.includes(nextEmployee.city) ? 
    foundValues : foundValues.concat(nextEmployee.city), []
);

console.log( cities );
like image 32
PeterKA Avatar answered Nov 02 '25 09:11

PeterKA