I need to find unique objects from array based on 2 properties as below. When "class" and "fare" match, I need to pull out unique values and get them in results array.
Source:
var arr = [{class:"second", fare: "a"},
{class:"second", fare: "b"},
{class:"first", fare: "a"},
{class:"first", fare: "a"},
{class:"second", fare: "a"},
{class:"first", fare: "c"}
]
Expected result:
var result = [{class:"second", fare: "a"},
{class:"second", fare: "b"},
{class:"first", fare: "a"},
{class:"first", fare: "c"}
]
I looked over in SO and was able to find answer which is filtered based on one property (Create array of unique objects by property), but couldn't find which could do based on 2 properties.
You could build a combined key for the hash table and filter the given array.
var arr = [{ class: "second", fare: "a" }, { class: "second", fare: "b" }, { class: "first", fare: "a" }, { class: "first", fare: "a" }, { class: "second", fare: "a" }, { class: "first", fare: "c" }],
result = arr.filter(function (a) {
var key = a.class + '|' + a.fare;
if (!this[key]) {
this[key] = true;
return true;
}
}, Object.create(null));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
The same without (mis)using thisArg
of Array#filter
.
var array = [{ class: "second", fare: "a" }, { class: "second", fare: "b" }, { class: "first", fare: "a" }, { class: "first", fare: "a" }, { class: "second", fare: "a" }, { class: "first", fare: "c" }],
seen = Object.create(null),
result = array.filter(o => {
var key = ['class', 'fare'].map(k => o[k]).join('|');
if (!seen[key]) {
seen[key] = true;
return true;
}
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Using a combined key and a Map
const array = [
{ class: "second", fare: "a" },
{ class: "second", fare: "b" },
{ class: "first", fare: "a" },
{ class: "first", fare: "a" },
{ class: "second", fare: "a" },
{ class: "first", fare: "c" }
];
console.log(unique(array, ['class', 'fare']));
function unique(arr, keyProps) {
const kvArray = arr.map(entry => {
const key = keyProps.map(k => entry[k]).join('|');
return [key, entry];
});
const map = new Map(kvArray);
return Array.from(map.values());
}
You can use forEach
to loop and filter
or find
array property to find if the element exist in array
var arr = [{
class: "second",
fare: "a"
}, {
class: "second",
fare: "b"
}, {
class: "first",
fare: "a"
}, {
class: "first",
fare: "a"
}, {
class: "second",
fare: "a"
}, {
class: "first",
fare: "c"
}]
var _unArray = []; // new array without duplicate
arr.forEach(function(item) { // loop through array which contain duplicate
// if item is not found in _unArray it will return empty array
var isPresent = _unArray.filter(function(elem) {
return elem.class === item.class && elem.fare === item.fare
})
if (isPresent.length == 0) {
_unArray.push(item)
}
})
console.log(_unArray)
JSFIDDLE
Like most answers, convert to a map with keys being a concatenation of the values, then back to an array. This one uses reduce
.
const array = [
{ class: "second", fare: "a" },
{ class: "second", fare: "b" },
{ class: "first", fare: "a" },
{ class: "first", fare: "a" },
{ class: "second", fare: "a" },
{ class: "first", fare: "c" }
];
console.log(unique(array, ['class', 'fare']));
function unique(arr, keyProps) {
return Object.values(arr.reduce((uniqueMap, entry) => {
const key = keyProps.map(k => entry[k]).join('|');
if (!(key in uniqueMap)) uniqueMap[key] = entry;
return uniqueMap;
}, {}));
}
function unique(arr, keyProps) {
const kvArray = arr.map(entry => { // entry = {class: "second", fare: "a"}
// keyProps = ["class", "fare"]
// k="class"; entry[k]="second";
// k="fare"; entry[k]="a"
// keyProps.map(k => entry[k])=["second","a"];
// .join("|")="second|a";
const key = keyProps.map(k => entry[k]).join('|'); // key = "second|a"
return [key, entry]; // ["second|a",{"class":"second","fare":"a"}]
});
// kvArray = [["second|a",{"class":"second","fare":"a"}],["second|b",
// {"class":"second","fare":"b"}],["first|a",{"class":"first","fare":"a"}],
// ["first|a",{"class":"first","fare":"a"}],["second|a",
// {"class":"second","fare":"a"}],["first|c",{"class":"first","fare":"c"}]]
const map = new Map(kvArray); // this will remove duplicate entry with same key.
return Array.from(map.values()); // convert back to array from all entry's value
}