Remove equal objects from array - javascript

I have the following problem in JavaScript: I want to check an array for duplicates. My example array only has 6 objects here.
var list = [
{id: "1", label: "Nils"},
{id: "2", label: "Max"},
{id: "3", label: "Thomas"},
{id: "4", label: "Tom"},
{id: "5", label: "Joschua"},
{id: "5", label: "Joschua"}];
In the later project it can also be more than 500, which I import via a CSV file.
And now I want to remove duplicates. At first I tried the set method:
var newList = [... new Set(list)];
console.log(newList);
The result is false. The array has the same objects.
Then I tried a simple if query:
if(list[4]==list[5]){
console.log("equal") }else{
console.log("unequal")}
The result is unequal. I don't understand why.
The array should look like this:
[{ id: '1', label: 'Nils' },
{ id: '2', label: 'Max' },
{ id: '3', label: 'Thomas' },
{ id: '4', label: 'Tom' },
{ id: '5', label: 'Joschua' }]

If the ids are meant to be unique, you can use Array#filter with a Set based on the id.
var list = [
{id: "1", label: "Nils"},
{id: "2", label: "Max"},
{id: "3", label: "Thomas"},
{id: "4", label: "Tom"},
{id: "5", label: "Joschua"},
{id: "5", label: "Joschua"}];
const set = new Set,
res = list.filter(x => !set.has(x.id) && set.add(x.id));
console.log(res);

Set cannot compare object altogether, it only works with primitives types like number or string.
You can use a Map that is based on a key/value paradigm though, like :
const list = [
{id: '1',label: 'Nils'},
{id: '2', label: 'Max'},
{id: '3', label: 'Thomas'},
{id: '4', label: 'Tom'},
{id: '5', label: 'Joschua'},
{id: '5', label: 'Joschua'},
];
const map = new Map();
// Push the values into the map
list.forEach(({
id,
label,
}) => map.set(id, label));
// Transform the map into an array of object
const uniqueList = Array.from(map, ([id, label]) => ({
id,
label,
}));
console.log(uniqueList);
Or using an Array.reduce combined with an Array.map
const list = [
{id: '1', label: 'Nils'},
{id: '2', label: 'Max'},
{id: '3', label: 'Thomas'},
{id: '4', label: 'Tom'},
{id: '5', label: 'Joschua'},
{id: '5', label: 'Joschua'},
];
const uniqueList = Object.entries(list.reduce((tmp, {
id,
label,
}) => {
tmp[id] = label;
return tmp;
}, {})).map(([
id,
label,
]) => ({
id,
label,
}));
console.log(uniqueList);

Then I tried a simple if query:
if(list[4]==list[5]){ console.log("equal") }else{
console.log("unequal")} The result is unequal. I don't understand why.
== uses Abstract Equality Comparison Algorithm.
At first this algorithm checks if the types are the same
-> which they are.
Then the algorithm proceeds with the first step, and goes down to check if they both referencing the same object
-> they don't referencing the same object
That is the reason why it prints out false
Each usage of {} creates a new object, so this check fails and the result is false.
let a = {}
let b = {}
console.log(a==b);
Or like in your example
let a = {id: "5", label: "Joschua"};
let b = {id: "5", label: "Joschua"};
console.log(a==b);
Solution
To check if two objects are equal you can do the following
let a = {
id: 5,
name: "Max"
}
let b = {
id: 5,
name: "Max"
}
function areTheObjectsEqual(obj1, obj2) {
let keysObj1 = Object.keys(obj1);
let keysObj2 = Object.keys(obj2);
// first check if they have the same amount of keys, if not return false
if (keysObj1.length !== keysObj2.length) {
return false;
}
let valuesObj1 = Object.values(obj1);
let valuesObj2 = Object.values(obj2);
// then compare if they have the same values
for(let i = 0; i < valuesObj1.length; i++){
if(valuesObj1[i] !== valuesObj2[i]){
return false;
}
}
return true;
}
console.log(areTheObjectsEqual(a,b));

Related

How to filter array of objects by another array of objects by property using javascript

I have two nested array of objects, how to compare two array of objects by
id from arrobj1 and assignId from arrobj2 using javascript
So, I would to know how to compare array of objects by id and assignId and return array of objects using javascript
Tried
const result = arrobj1.filter(arr1 => {
arrobj2.find(arr2 => arr2.assignId === arr1.id)
});
var arrobj1 =[
{id: 1, name: 'xxx', value:100},
{id: 2, name: 'yyy', value:200},
{id: 3, name: 'zzz', value:400}
]
var arrobj2 =[
{country: 'IN', name: 'lina', assignId:2},
{country: 'MY', name: 'john', assignId:3},
{country: 'SG', name: 'peter', assignId:6}
]
Expected Code:
[
{id: 2, name: 'yyy', value:200},
{id: 3, name: 'zzz', value:400}
]
You have it almost correct, but you need to return in your filter, either by explicitly adding the return keyword or by removing the braces to use the arrow function's implicit return:
const result = arrobj1.filter(arr1 =>
arrobj2.find(arr2 => arr2.assignId === arr1.id)
)
// or
const result = arrobj1.filter(arr1 => {
return arrobj2.find(arr2 => arr2.assignId === arr1.id)
})
We can combine Array.filter() and Array.some() to make it more simple
let result = arrobj1.filter(a1 => arrobj2.some(a2 => a2.assignId === a1.id) )
console.log(result)
For your code,the reason is that you have missing return when invoke find
var arrobj1 =[
{id: 1, name: 'xxx', value:100},
{id: 2, name: 'yyy', value:200},
{id: 3, name: 'zzz', value:400}
]
var arrobj2 =[
{country: 'IN', name: 'lina', assignId:2},
{country: 'MY', name: 'john', assignId:3},
{country: 'SG', name: 'peter', assignId:6}
]
let result = arrobj1.filter(a1 => arrobj2.some(a2 => a2.assignId === a1.id) )
console.log(result)
You can generally go with the filter and some combination as #flyingfox mentioned in the answer, But if you'd have thousands of records then your time complexity would increase which you can solve by removing the nested some loop.
So more performant code would look like the following for a bigger data set.
And yes, Either use return with braces or simply remove the braces for one-liner returns!
var arrobj1 = [
{ id: 1, name: 'xxx', value: 100 },
{ id: 2, name: 'yyy', value: 200 },
{ id: 3, name: 'zzz', value: 400 },
]
var arrobj2 = [
{ country: 'IN', name: 'lina', assignId: 2 },
{ country: 'MY', name: 'john', assignId: 3 },
{ country: 'SG', name: 'peter', assignId: 6 },
]
var obj = {}
for (const elem of arrobj2) {
obj[elem.assignId] = true
}
let result = arrobj1.filter((a1) => obj[a1.id])
console.log(result)

How to remap array in React [duplicate]

This question already has answers here:
How to rename properties of objects in array in javascript?
(5 answers)
Closed 4 months ago.
How to do a remapo for new objects like:
...
const inputArr = [
{id: '1', name: "test1", routeName: "somethig/something"},
{id: '2', name: "something2", routeName: "foo/bar"},
{id: '3', name: "someanothrelement", routeName: "test/test"}
]
//to =>
const resultStructureArr = [
{ id: '1', value: 'somethig/something', label: 'test1' },
{ id: '2', value: 'foo/bar', label: 'something2' },
{ id: '3', value: 'test/test', label: 'someanothrelement' },
];
...
Here is the jsfiddle
Just using map() can do it
const inputArr = [
{id: '1', name: "test1", routeName: "somethig/something"},
{id: '2', name: "something2", routeName: "foo/bar"},
{id: '3', name: "someanothrelement", routeName: "test/test"}
]
let result = inputArr.map(a => ({'id':a.id,'label':a.name,'value':a.routeName}))
console.log(result)
We can use traditional for loop for this. Where we may loop to the length of list and for each iteration we may add new object into result array using Array.prototype.push method. Secondly we are doing the same thing with foreach loop. Third I'm using Array.prototype.map method, Which creates a new result for each iteration, in our case we are returning our new object. Lastly we are using Array.prototype.reduce method, with this method we can initialize a starting value which in my case I'm using empty array, then for each iteration I'm pushing a new object in that array and returning it.
const inputArr = [
{ id: "1", name: "test1", routeName: "somethig/something" },
{ id: "2", name: "something2", routeName: "foo/bar" },
{ id: "3", name: "someanothrelement", routeName: "test/test" },
];
// Using for loop
let result = [];
for (let i = 0; i < inputArr.length; i++) {
result.push({
id: inputArr[i].id,
value: inputArr[i].routeName,
label: inputArr[i].name,
});
}
console.log(result);
result = [];
// using foreach loop
inputArr.forEach((item) => {
result.push({ id: item.id, label: item.name, value: item.routeName });
});
console.log(result);
result = [];
// using map
result = inputArr.map((item) => ({
id: item.id,
label: item.name,
value: item.routeName,
}));
console.log(result);
result = [];
// using reduce
result = inputArr.reduce((acc, curr) => {
acc.push({ id: curr.id, label: curr.name, value: curr.routeName });
return acc;
}, []);
console.log(result);

Compare and return boolean if two array of objects has the values or not

I have two array of objects which are like,
let A = [{id: "1"}, {id: "2"},{id: "3" }]
let B = [{id: "3"}, {id: "2"}]
Now, I am iterating over A.
return _.map(A) => ({
id: A.id,
isAvaliable: //This needs to be like weather B includes A on the basis of ID , means does B object has this A client ID if yes then set it true or false
})
So, final object which I will get will be,
const result = [{
{id: "1", isavaliable: false},
{id: "2", isavaliable: true},
{id: "3", isavaliable: true},
}
]
So, How do I achieve this ?
Thanks.
First make an array or Set of the B ids, then you can .map A and set isavailable by whether the id is included in the set:
const A = [{id: "1"}, {id: "2"},{id: "3" }];
const B = [{id: "3"}, {id: "2"}];
const haveIds = new Set(B.map(({ id }) => id));
const result = A.map(({ id }) => ({ id, isavailable: haveIds.has(id) }));
console.log(result);
No need to rely on an external library, Array.prototype.map works just fine.
let A = [{ id: "1" }, { id: "2" }, { id: "3" }];
let B = [{ id: "3" }, { id: "2" }];
const merge = (arr1, arr2) =>
arr1.map((a) => ({
id: a.id,
isAvaliable: !!arr2.find((b) => b.id === a.id),
}));
console.log(merge(A, B));
Use lodash 'find' to check id in array B
const A = [{id: '1'}, {id: '2'}, {id: '3' }];
const B = [{id: '3'}, {id: '2'}];
const C = _.map(A, item => {
return {
id: item.id,
isAvailable: _.find(B, {id: item.id}) ? true : false
};
});

method find javascript deep array object RN react native

Here is a part of my object
const category = {
fr: {
list: [
{id: 1, label: 'coucou'},
{id: 2, label: 'moi'},
{id: 3, label: 'ici'},
{id: 4, label: 'maintenant'},
{id: 5, label: 'demain'},
]}}
const lang = fr;
const anyId = 3;
I don't know why when doing the following:
const result = category[lang].list.find(item => item.id === anyId) console.log(result)
Throws the following:
// undefined category[lang].list.find(item => item.id === anyId) is not
a function, or just undefined
same result for .map or .filter
console.log(category) returns no error
console.log(category[lang]) returns no error
console.log(category[lang].list) returns no error
but anything else will return an error.
It drives me crazy, any help will be highly appreciated.
Use const lang = "fr" instead of const lang = fr, because fr is an undefined variable but "fr" is a string. So you'll get category["fr"] instead of category[fr].
const category = {
fr: {
list: [
{id: 1, label: 'coucou'},
{id: 2, label: 'moi'},
{id: 3, label: 'ici'},
{id: 4, label: 'maintenant'},
{id: 5, label: 'demain'},
]}}
const lang = "fr";
const anyId = 3;
const result = category[lang].list.find(item => item.id === anyId)
console.log(result)
You want category.fr not just fr, as the variable fr does not exist.
Now that lang contains your fr object, you can simply do a .find() on lang.list as below:
const category = {
fr: {
list: [
{id: 1, label: 'coucou'},
{id: 2, label: 'moi'},
{id: 3, label: 'ici'},
{id: 4, label: 'maintenant'},
{id: 5, label: 'demain'},
]}}
// Fill param from a variable, or anything, as long as it's a string:
const param = 'fr';
// Use brackets here, as you want `category.fr` and not `category.param`:
const lang = category[param];
//Or you can simply use:
//const lang = category.fr; //If this is not a parameter, or user input
const anyId = 3;
console.log(lang);
console.log(lang.list.find(item => item.id === anyId));
It works on mdn sandbox
const category = {
fr: {
list: [
{id: 1, label: 'coucou'},
{id: 2, label: 'ici'},
{id: 3, label: 'demain'},
{id: 4, label: 'matin'},
]
}
};
var lang ='fr';
var catID = 3;
console.log(lang);
console.log(catID);
console.log(category);
console.log(category[lang]);
console.log(category[lang].list);
var found = category[lang].list.find(function(element) {
return element.id === catID;
});
console.log(found.label); // demain
just add a return inside the callback function,
but it still doesn't work on react-native
so the problem remains

Javascript how to filter an array using forEach() inside filter()

I have an array of objects and I'd like to filter it based on the objects property values. I'd like to filter it by different properties, so it needed to be dynamic. For this I have an input field where I type and then filter the array. So, let's say I have these 2 different arrays:
const array_one = [
{id: 1, code: 'ABC123', name: 'John'},
{id: 2, code: 'DEF456', name: 'Stew'},
// ...
];
const array_two = [
{id: 1, value: '012345', company: 'Company 01' },
{id: 2, value: '678910', company: 'Company 02' },
// ...
];
I want a function where I can filter the first array based on the name, also If I want to filter the second array, I want to filter it by the value.
For this, I built this function:
filterArray(array: Array<any>, fields: Array<any>, value: string) {
value = this.convertString(value);
array = array.filter((item) => {
fields.forEach(obj => {
if ( item[obj] ) {
const _newObj = this.convertString(item[obj]);
if ( _newObj.indexOf(value) !== -1 ) {
console.log(item);
return item;
}
}
});
});
return array;
}
// convertString() is just another function to replace accents, spaces, etc...
Then I call it like this:
filterArray(originalArray, ['name'], valueFromInput);
// or...
filterArray(originalArray, ['value'], valueFromInput);
// or even...
filterArray(originalArray, ['value', 'company'], valueFromInput);
But the array filtered is always returnin empty, even if the console inside the indexOf verification prints the correct object on the console.
What am I doing wrong here? Because it's filtering properly, I have manually checked it, but it doesn't add to the new filtered array.
You can iterate the fields using Array#some, and if one of them is equal to value return the item:
const array_one = [
{id: 1, code: 'ABC123', name: 'John'},
{id: 2, code: 'DEF456', name: 'Stew'}
];
const array_two = [
{id: 1, value: '012345', company: 'Company 01' },
{id: 2, value: '678910', company: 'Company 02' }
];
const filterArray = (array, fields, value) => {
fields = Array.isArray(fields) ? fields : [fields];
return array.filter((item) => fields.some((field) => item[field] === value));
};
console.log(filterArray(array_one, 'name', 'Stew'));
console.log(filterArray(array_two, ['id', 'company'], 2));
console.log(filterArray(array_two, ['id', 'company'], 'Company 02'));
If you want to make the filter about more than one filed then the value that you send it to the function, should be also array.
In my code below I assume that you want to return the object that Achieves all conditions (contains all properties that you send to the function with the same value)
const array_one = [
{id: 1, code: 'ABC123', name: 'John'},
{id: 2, code: 'DEF456', name: 'Stew'},
];
const array_two = [
{id: 1, value: '012345', company: 'Company 01' },
{id: 2, value: '678910', company: 'Company 02' },
];
function filterArray(array, fields, value) {
array = array.filter((item) => {
const found = fields.every((field, index) => {
return item[field] && item[field] === value[index]
})
return found
});
return array;
}
console.log(filterArray(array_one, ['name'], ['Stew']));
console.log(filterArray(array_two, ['id', 'company'], [1,'Company 01']));

Categories

Resources