Array.filter() to remove duplicate Ojects - javascript

I would like to fuse Array.filter() function to remove duplicate objects
I am able to achieve in the case of string or integer arrays. But I am not able to achieve the same with array of objects as in the second case of names
const names = ['John', 'Paul', 'George', 'Ringo', 'John'];
let x = names => names.filter((v, i, arr) => arr.indexOf(v) === i);
console.log(x(names)); //[ 'John', 'Paul', 'George', 'Ringo' ]
const names = [
{ name: "John" },
{ name: "Paul" },
{ name: "George" },
{ name: "Ringo" },
{ name: "John" } ];
// returns the same original array
Could you please help?

Using Array#reduce() and a Map accumulator then spread the values() of the Map into array
const names = [
{ name: "John" },
{ name: "Paul" },
{ name: "George" },
{ name: "Ringo" },
{ name: "John" } ];
const unique = [... names.reduce((a,c)=>(a.set(c.name,c)),new Map).values()]
console.log(unique)

Use Array.reduce and Object.values
Iterate over the array and create an object with key as name and value as object from array. In case of objects with same name, the value will be overwritten in resultant object. Finally use Object.values to collect all the unique objects.
const names = [{ name: "John" },{ name: "Paul" },{ name: "George" },{ name: "Ringo" },{ name: "John" } ];
let result = Object.values(names.reduce((a,c) => Object.assign(a, {[c.name]:c}),{}));
console.log(result);
For tweaking - Plunker

const names = [
{ name: "John" },
{ name: "Paul" },
{ name: "George" },
{ name: "Ringo" },
{ name: "John" }
];
/* unique => Filter: Remove all duplicate items from an array. Works with plain objects as well, since we stringify each array item.
* #type public Function
* #name unique
* #return Function( item )
* #notes
*/
const unique = () => {
const seen = {};
return item => {
const json = JSON.stringify( item );
return seen.hasOwnProperty( json )
? false
: ( seen[ json ] = true );
};
};
const result = names.filter( unique() );
console.log( result );

You could use lodash's _uniqBy for this:
const names = [
{ name: "John" },
{ name: "Paul" },
{ name: "George" },
{ name: "Ringo" },
{ name: "John" } ];
const result = _uniqBy(names, 'name');

This can be done with the help of Sets as well
var names = [{ name: "John" },{ name: "Paul" },{ name: "George" },{ name: "Ringo" },{ name: "John" } ];
var result = Array.from(
names.reduce((s, d) => s.add(d.name), new Set)
, d => ({ name: d })
)
console.log(result)

Keith had a great suggestion to use findIndex with filter instead of indexOf. Object literals are always unique references, so we cannot compare them. We can however compare the name keys between the objects. We can do this with the aforementioned functions.
const names = [
{ name: "John" },
{ name: "Paul" },
{ name: "George" },
{ name: "Ringo" },
{ name: "John" }
];
console.log(names.filter(({name1}, i, a) => {
return i == a.findIndex(({name2}) => {
return name1 == name2;
});
});

const names = ['John', 'Paul', 'George', 'Ringo', 'John'];
function removeDups(names) {
let unique = {};
names.forEach(function(i) {
if(!unique[i]) {
unique[i] = true;
}
});
return Object.keys(unique);
}
removeDups(names); //'John', 'Paul', 'George', 'Ringo'

Related

check array of objects if specific value is unique across all the array

I have an array like this
const arr = [{ name: 'sara' }, { name: 'joe' }];
and i want to check if name is unique across the array so
const arr = [{ name: 'sara' }, { name: 'joe' }];//sara is unique //true
const arr = [{ name: 'sara' }, { name: 'sara' },{ name: 'joe' }];//sara is unique //false
i know there's array.some but it doesn't help in my situation
whats is the best way to achieve that using javascript thanks in advance
You could take a single loop and a Set for seen value.
isUnique is a function which takes a property name and returns a function for Array#every.
const
isUnique = (key, s = new Set) => o => !s.has(o[key]) && s.add(o[key]),
a = [{ name: 'sara' }, { name: 'joe' }],
b = [{ name: 'sara' }, { name: 'sara' }, { name: 'joe' }];
console.log(a.every(isUnique('name'))); // true
console.log(b.every(isUnique('name'))); // false
i have this implementation and it dose the job
const arr = [{ name: "salah" }, { name: "joe" }];
let bols = [];
arr.forEach((item1, i1) => {
arr.forEach((item2, i2) => {
if (i1 !== i2) {
bols.push(item2.name === item1.name);
}
});
});
bols.some((item) => item === true);

How to convert array of objects into enum like key value pair in javascript?

I have an array
const a = [
{ name: "read-web-courses" },
{ name: "example" },
{ name: "t_gql" },
{ name: "ddddd" },
];
I am trying it to reduce it to the below given output , However I am stuck
Output
{0:"read-web-courses",1:"example",2:"t_gql",3:"ddddd"}
You could map the wanted property and assign the pairs to the object.
const
array = [{ name: "read-web-courses" }, { name: "example" }, { name: "t_gql" }, { name: "ddddd" }],
result = Object.assign({}, array.map(({ name }) => name));
console.log(result);
You can use Array.reduce like below.
const a = [
{ name: "read-web-courses" },
{ name: "example" },
{ name: "t_gql" },
{ name: "ddddd" },
];
const convert = arr => (
arr.reduce((total, value, index) => {
total[index] = value.name;
return total;
}, {})
)
console.log(convert(a));
This is accomplished using Array#reduce, where you can use the index from the reduce callback as the key of the new object:
const a = [ { name: "read-web-courses" }, { name: "example" }, { name: "t_gql" }, { name: "ddddd" }];
const res = a.reduce((r, o, i) => {
r[i] = o.name;
return r;
}, {});
console.log(res);
Also one more approach using Object#fromEntries and Array#map, where each object is converted to an array of key, value pairs:
const a = [ { name: "read-web-courses" }, { name: "example" }, { name: "t_gql" }, { name: "ddddd" }];
const res = Object.fromEntries(a.map((o, i) => [i, o.name]));
console.log(res)

Comparing two Objects by id and creating the new one

So I have two objects with this structure:
const obj1 = { data:
[ {
id: 1,
name: 'Linda'
},
{
id: 2,
name: 'Mark'
}
];
const obj2 = [
{
id: 1,
salary: "2000, 60 USD"
},
undefined
],
[
{
id: 2,
salary: "4000, 50 USD"
},
undefined
]
I need to make a function to combine both of these into one object, based on id.
So the final results would be:
const finalObj = { data:
[ {
id: 1,
name: 'Linda',
salary: "2000, 60 USD"
},
{
id: 2,
name: 'Mark',
salary: "4000, 50 USD"
}
];
I have checked other questions, but could not find anything that would help. It can be done with lodash afaik, but don't know how.
I have tried the following:
finalObj = obj1.data.map(x => {
return {
...x,
...obj2
}
But it didn't map correctly.
Thanks.
EDIT: Updated obj2 response.
You can array#concat both your array and then using array#reduce and an object lookup with id, merge your objects. Then return all the values from this object.
const obj1 = { data: [{ id: 1, name: 'Linda' }, { id: 2, name: 'Mark' }]},
obj2 = { data: [{ id: 1, salary: "2000, 60 USD"}, { id: 2, salary: "4000, 50 USD"}]},
result = Object.values(obj1.data.concat(obj2.data).reduce((r,o) => {
r[o.id] = r[o.id] || {};
r[o.id] = {...r[o.id], ...o};
return r;
},{}));
console.log(result);
You could take a Map for collecting all properties of the same id in an object. Later get the values of the map.
const join = o => o && map.set(o.id, Object.assign(map.get(o.id) || {}, o));
var obj1 = { data: [{ id: 1, name: 'Linda' }, { id: 2, name: 'Mark' } ]},
obj2 = [{ id: 1, salary: "2000, 60 USD" }, undefined, { id: 2, salary: "4000, 50 USD" }, undefined],
map = new Map,
result;
obj1.data.forEach(join);
obj2.forEach(join);
result = { data: Array.from(map.values()) };
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Another way
const res = {
...obj1, // take the initial object
data: obj1.data.map(item => ({ // rewrite data property by iterate each item
// and merge item with corresponding
// object from obj2
...item, // take the item object
...obj2.find(({ id }) => id === item.id) // find corresponding object
}))
};
Here is an approach which would combine the objects and not overwrite the properties but only add the ones that are missing as well as avoid the undefined etc:
const names = {data: [{ id: 1, name: 'Linda' },{ id: 2, name: 'Mark' }]}
const salaries = [{ id: 1, salary: "2000, 60 USD" }, undefined]
var result = _.mapValues(names.data, x => {
let hit = _.find(salaries, y => y ? y.id === x.id : null)
return hit ? _.defaults(x, hit) : x
})
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
We are using mapValues to get to the values of names.data and look through them and for each of them get a hit in the salaries. If the hit exists we default the props of the hit with the current data object and return. Hope this helps.

How do I use the reduce method in loDash? Or Javascript Take a Array of Objects and Make one Object

I have a Array of Objects:
` tempArray = [
{ name: 'Lion-O' },
{ gender: 'Male' },
{ weapon: 'Sword of Omens' },
{ status: 'Lord of the Thundercats' },
]
`
Object I want to Transform into:
`{
name: 'Lion-O',
gender: 'Male,',
weapon: 'Sword of Omens',
status: 'Lord of the Thundercats'
}`
I tried to use reduce in LoDash;
const tempObj = _.reduce(tempArray, (r, v, k) => {
return r
})
console.log(tempObj);
//=> { name: 'Lion-O' }
I'm not sure how I should iterate over the Array? Looked at Doc's their example shows Adding or Pushing onto a Array .. I just want a Object.. I know it can be done. If their is a better way I'm open to that as well
Thanks in advance.
Shorter equivalent solution :
const tempArray = [
{ name: 'Lion-O' },
{ gender: 'Male' },
{ weapon: 'Sword of Omens' },
{ status: 'Lord of the Thundercats' },
];
const newObj = Object.assign({}, ...tempArray);
console.log(newObj);
// Object {name: "Lion-O", gender: "Male", weapon: "Sword of Omens", status: "Lord of the Thundercats"}
tempArray = [
{ name: 'Lion-O' },
{ gender: 'Male' },
{ weapon: 'Sword of Omens' },
{ status: 'Lord of the Thundercats' },
]
var newObject = {};
for (var index in tempArray) {
thisObject = tempArray[index];
for (var key in thisObject) {
newObject[key] = thisObject[key];
}
}
console.log(newObject);

Iterate through JavaScript objects to produce an array of objects

I have an array of objects. One of the objects looks like this:
obj1 = {
name: 'rich',
email: 'rich#test.com',
date: {
greg : {
name: 'greg',
id: 1234}
}
}
How can I iterate through this array of objects (called usersArray) and add it to another array of objects (called usersArrayObj) with each object containing the name of the user (e.g. rich) and the name of the other (e.g. greg)
so that my end result would look like the below:
obj1 = {
name: 'rich',
pairName: 'greg',
}
I have tried to use hasOwnProperty and so forth but they behaving a little bit funky...
You can map the array like this:
var myArray = [
{ name: 'rich', email: 'rich#test.com', date: { greg: { name: 'greg', id: 1234 } } },
{ name: 'foo', email: 'foo#test.com', date: { bar: { name: 'bar', id: 5678 } } }
];
var results = myArray.map(function(item) { // For each item in the array
return { // Return an object,
name: item.name, // Using the current item's name
pairName: Object.keys(item.date)[0] // And the first key found on `item.date`
};
});
console.log(results);
This solution uses ES6. Use Array.prototype.map() and extract the object (inside greg:) using Object.values() (the the browser's support in the link):
const arr = [{
name: 'rich',
email: 'rich#test.com',
date: {
greg: {
name: 'greg',
id: 1234
}
}
}];
const result = arr.map(({ name, date }) => ({
name,
pairName: Object.values(date)[0].name
}));
console.log(result);
You can use Array.prototype.map() to crate the new array
To select the first key inside the object data you can use Object.keys() that will return you an array of a given object's own enumerable properties. You can then select the first element [0]
var usersArray = [{
"name": 'rich',
"email": 'rich#test.com',
"date": {
"greg": {
"name": 'greg',
"id": 1234
}
}
}, {
"name": 'jason',
"email": 'jason#test.com',
"date": {
"mickael": {
"name": 'mickael',
"id": 5678
}
}
}];
var usersArrayObj = usersArray.map(function(user) {
return {
"name": user.name,
"pairName": Object.keys(user.date)[0]
}
});
console.log(usersArrayObj);
.as-console-wrapper { max-height: 100% !important; top: 0; }
for this case what you can use is Object.keys() JS function.
obj2= {
name:obj1.name,
pairName: Object.keys(obj1.date)[0]
}
var arr = [{
name: 'rich',
email: 'rich#test.com',
date: {
greg : {
name: 'greg',
id: 1234}
}
}]
var newArr = [];
for (var i = 0; i < arr.length; i++) newArr[i] = {
name: arr[i].name,
pairName: Object.keys(arr[i].date)[0]
};
JSON.stringify(newArr); // "[{"name":"rich","pairName":"greg"}]"

Categories

Resources