Chris
Chris

Reputation: 355

Distinct values from object property in array when property may not be present

I'm creating an array of distinct values based on a single property in an array of objects. Nothing unusual, but the JSON I'm working with may not have that property. The result is I'm getting an item in the new array with a value of undefined. Is there a way to prevent this?

const cars = [{
    "name": "Toyota",
    "model": "Corolla"
  },
  {
    "name": "Toyota",
    "model": "Supra"
  },
  {
    "name": "Toyota",
    "model": "Rav4"
  },
  {
    "name": "Toyota"
  }
];

const distinctModels = [...new Set(cars.map(car => car.model))];

console.log(distinctModels);

EDIT - I should have mentioned that I'm interested to know if there's a way to do this whilst still utilising new Set.

Upvotes: 2

Views: 56

Answers (4)

arizafar
arizafar

Reputation: 3122

You can use Array.prototype.flatMap to do it in one loop, by returning an empty array when value is not there.

const cars = [{
	"name": "Toyota",
	"model": "Corolla"
},
{
	"name": "Toyota",
	"model": "Supra"
},
{
	"name": "Toyota",
	"model": "Rav4"
},
{
	"name": "Toyota"
}
];

const distinctModels = [...new Set(cars.flatMap(car => car.model || []))];

console.log(distinctModels);

Upvotes: 0

Nick Parsons
Nick Parsons

Reputation: 50664

If you want to filter and map at the same time (ie in the one statement) you can instead use .reduce() to better control what goes into your output array:

const cars = [{
    "name": "Toyota",
    "model": "Corolla"
  },
  {
    "name": "Toyota",
    "model": "Supra"
  },
  {
    "name": "Toyota",
    "model": "Rav4"
  },
  {
    "name": "Toyota"
  }
];

const distinctModels = [...new Set(cars.reduce(
                         (a, car) => car.model ? [...a, car.model] : a, []
                        ))];

console.log(distinctModels);

Upvotes: 0

ellipsis
ellipsis

Reputation: 12152

Use .hasOwnProperty to check if a property exists in the object or not

const cars = [{
    "name": "Toyota",
    "model": "Corolla"
  },
  {
    "name": "Toyota",
    "model": "Supra"
  },
  {
    "name": "Toyota",
    "model": "Rav4"
  },
  {
    "name": "Toyota"
  }
];

const distinctModels = []
cars.forEach(function(e){
e.hasOwnProperty('model')?distinctModels.push(e.model):false;
});
console.log(distinctModels);

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386540

You could post process the array and filter falsy values.

const cars = [{ name: "Toyota", model: "Corolla" }, { name: "Toyota", model: "Supra" }, { name: "Toyota", model: "Rav4" }, { name: "Toyota" }];

const distinctModels = [...new Set(cars.map(car => car.model))].filter(Boolean);

console.log(distinctModels);

Upvotes: 4

Related Questions