This question already has answers here:
How to get distinct values from an array of objects in JavaScript?
(63 answers)
Get all unique values in a JavaScript array (remove duplicates)
(91 answers)
Closed 6 years ago.
I have array with obejcts email and Id so I want delete duplicate elements who have similar ID's.
Example:
var newarray=[
{
Email:"test1#gmail.com",
ID:"A"
},
{
Email:"test2#gmail.com",
ID:"B"
},
{
Email:"test3#gmail.com",
ID:"A"
},
{
Email:"test4#gmail.com",
ID:"C"
},
{
Email:"test4#gmail.com",
ID:"C"
}
];
Now I need to delete Duplicate elements which have ID's are common.In the sence I am expecting final Array is
var FinalArray=[
{
Email:"test1#gmail.com",
ID:"A"
},
{
Email:"test2#gmail.com",
ID:"B"
},
{
Email:"test5#gmail.com",
ID:"C"
}
];
Use Array.prototype.filter to filter out the elements and to keep a check of duplicates use a temp array
var newarray = [{
Email: "test1#gmail.com",
ID: "A"
}, {
Email: "test2#gmail.com",
ID: "B"
}, {
Email: "test3#gmail.com",
ID: "A"
}, {
Email: "test4#gmail.com",
ID: "C"
}, {
Email: "test5#gmail.com",
ID: "C"
}];
// Array to keep track of duplicates
var dups = [];
var arr = newarray.filter(function(el) {
// If it is not a duplicate, return true
if (dups.indexOf(el.ID) == -1) {
dups.push(el.ID);
return true;
}
return false;
});
console.log(arr);
You could filter it with a hash table.
var newarray = [{ Email: "test1#gmail.com", ID: "A" }, { Email: "test2#gmail.com", ID: "B" }, { Email: "test3#gmail.com", ID: "A" }, { Email: "test4#gmail.com", ID: "C" }, { Email: "test5#gmail.com", ID: "C" }],
filtered = newarray.filter(function (a) {
if (!this[a.ID]) {
this[a.ID] = true;
return true;
}
}, Object.create(null));
console.log(filtered);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES6 with Set
var newarray = [{ Email: "test1#gmail.com", ID: "A" }, { Email: "test2#gmail.com", ID: "B" }, { Email: "test3#gmail.com", ID: "A" }, { Email: "test4#gmail.com", ID: "C" }, { Email: "test5#gmail.com", ID: "C" }],
filtered = newarray.filter((s => a => !s.has(a.ID) && s.add(a.ID))(new Set));
console.log(filtered);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you can use Javascript libraries such as underscore or lodash, I recommend having a look at _.uniq function in their libraries. From lodash:
_.uniq(array, [isSorted=false], [callback=_.identity], [thisArg])
Here you have to use like below,
var non_duplidated_data = _.uniq(newarray, 'ID');
Another solution using Array.prototype.reduce and a hash table - see demo below:
var newarray=[ { Email:"test1#gmail.com", ID:"A" }, { Email:"test2#gmail.com", ID:"B" }, { Email:"test3#gmail.com", ID:"A" }, { Email:"test4#gmail.com", ID:"C" }, { Email:"test5#gmail.com", ID:"C" } ];
var result = newarray.reduce(function(hash){
return function(prev,curr){
!hash[curr.ID] && (hash[curr.ID]=prev.push(curr));
return prev;
};
}(Object.create(null)),[]);
console.log(result);
.as-console-wrapper{top:0;max-height:100%!important;}
Related
I have a problem here that I can't deal with. There is little written about this on the internet. Well, when starting out, I need to make a function that will remove the duplicate data from the table, but the comparison of this data must be based on the data from the table object, below I will give an example because I do not know if I explained it well.
[
{
id: 1234,
user: {
nickname: 'a' <-
}
},
{
id: 1234,
user: {
nickname: 'b' <-
}
},
{
id: 1234,
user: {
nickname: 'a' <-
}
},
]
Data is to be compared according to user.nickname.
I tried to do it this way
array.filter((value, index) => array.indexOf (value.user.nickname) === index)
but all I got was a blank array
[]
If anyone can help, I will be grateful because I have this situation.
Your approach is wrong. Here's one way you can do it instead:
const mapOfNicknames = {};
array.forEach((e)=> {
const nick = e.user.nickname;
// check if nick already exists in map
if ( !mapOfNicknames[nick] ) {
mapOfNicknames[nick] = e;
}
});
// at this point, mapOfNicknames has a unique list
const uniqueArray = Object.keys(mapOfNicknames).map( k => mapOfNicknames[k] );
Using Array.filter as you try, should be a proper aproat:
const users = [
{
id: 1234,
user: {
nickname: "a",
},
},
{
id: 1234,
user: {
nickname: "b",
},
},
{
id: 1234,
user: {
nickname: "a",
},
},
];
let filteruniquebyUserName = users.filter(
(user, index, users) => users.findIndex((compareUser) => compareUser.user.nickname === user.user.nickname) === index
);
console.log(filteruniquebyUserName);
See: How to remove all duplicates from an array of objects?
Another way a little more extended but easier to understand:
const data = [
{
id: 1234,
user: {
nickname: "a",
},
},
{
id: 1234,
user: {
nickname: "b",
},
},
{
id: 1234,
user: {
nickname: "b",
},
},
{
id: 1234,
user: {
nickname: "a",
},
},
];
let elementRepeated = [];
let filteruniquebyUserName = data.filter((user, index, data) => {
if(elementRepeated.includes(user.user.nickname)) return;
const numberOfRepeatUser = data.filter(element => element.user.nickname === user.user.nickname).length;
if(numberOfRepeatUser > 1) elementRepeated.push(user.user.nickname);
return user
});
console.log(filteruniquebyUserName);
Apparently you can't do an indexOf check in a nested object like you are doing it right now. See: Javascript indexOf on an array of objects
This question already has answers here:
How can I remove a specific item from an array in JavaScript?
(142 answers)
Closed 4 years ago.
I have an array of objects in my javascript application, looks something like
var data = [
{
id:2467,
name:'alex',
grade:'B',
},
{
id:5236,
name:'bob',
grade:'A-',
},
{
id:1784,
name:'carl',
grade:'C',
},
{
id:5841,
name:'dave',
grade:'AA',
},
{
id:3278,
name:'harry',
grade:'B+',
},
]
Now I have to remove or pop an object from this array on the basis of object id, using a function something like
function removeStudent(id){
//logic for removing object based on object id
}
It should be like
removeStudent(5236);
then the data array afterwards should be like
var data = [
{
id:2467,
name:'alex',
grade:'B',
},
{
id:1784,
name:'carl',
grade:'C',
},
{
id:5841,
name:'dave',
grade:'AA',
},
{
id:3278,
name:'harry',
grade:'B+',
},
]
I tried using pop() but I think that will remove the last element from the array, not the specific one.
I have looked at this post of removing an element from array
How do I remove a particular element from an array in JavaScript?
but I didn't find my answer here respected to objects
Needed help!
You can try with Array.prototype.filter():
function removeStudent(data, id) {
return data.filter(student => student.id !== id);
}
It will create a copy of the input data array.
const newData = removeStudent(data, 5236);
Use Array.findIndex and Array.splice
var data = [ { id:2467, name:'alex', grade:'B', }, { id:5236, name:'bob', grade:'A-', }, { id:1784, name:'carl', grade:'C', }, { id:5841, name:'dave', grade:'AA', }, { id:3278, name:'harry', grade:'B+', }];
function removeStudent(_id){
var index = data.findIndex(({id}) => id === _id);
if(index !== -1) data.splice(index,1);
}
removeStudent(5236);
console.log(data);
Use array filter method. It will return a new array of matched elements.In your case you need to return all the objects where id is not the the one which is passed in argument
var data = [{
id: 2467,
name: 'alex',
grade: 'B',
},
{
id: 5236,
name: 'bob',
grade: 'A-',
},
{
id: 1784,
name: 'carl',
grade: 'C',
},
{
id: 5841,
name: 'dave',
grade: 'AA',
},
{
id: 3278,
name: 'harry',
grade: 'B+',
},
]
function removeStudent(id) {
return data.filter(function(item) {
return item.id !== id;
})
}
console.log(removeStudent(5236));
You have to use findIndex instead, by passing a callback function as argument
var data = [ { id:2467, name:'alex', grade:'B', }, { id:5236, name:'bob', grade:'A-', }, { id:1784, name:'carl', grade:'C', }, { id:5841, name:'dave', grade:'AA', }, { id:3278, name:'harry', grade:'B+', }, ]
let id = 5236;
data.splice(data.findIndex(p => p.id == id), 1);
console.log(data);
You can use filter() but make sure you reassign the filter result to data to overwrite the original value:
var data = [
{
id:2467,
name:'alex',
grade:'B',
},
{
id:5236,
name:'bob',
grade:'A-',
},
{
id:1784,
name:'carl',
grade:'C',
},
{
id:5841,
name:'dave',
grade:'AA',
},
{
id:3278,
name:'harry',
grade:'B+',
},
];
function removeStudent(data, id){
return data.filter(student => student.id !== id);
}
data = removeStudent(data, 5236);
console.log(data);
The array
const users = dedup([
{ id: 1, email: 'foo#example.com' },
{ id: 2, email: 'sho#example.com' },
{ id: 1, email: 'bin#example.com' },
]);
/* would ideally like it to return
Object {
email: "foo#example.com",
email: "bin#example.com",
id:1
}, Object {
email: "sho#example.com",
id:2
} */
The Hash Table
function dedup(arr) {
var hashTable = {};
return arr.filter(function (el) {
var key = JSON.stringify(el);
var match = Boolean(hashTable[key]);
return (match ? false : hashTable[key] = true);
});
}
My returns statement that only filters out exact duplicates and doesn't join similar id's with different email addresses
console.log(users);
/* currently returns
Object {
email: "foo#example.com",
id:1
}, Object {
email: "sho#example.com",
id:2
},
{ id: 1, email: 'bin#example.com' },
]); */
function dedup(arr) {
var hashTable = {};
arr.forEach(function(el) {
if (!hashTable.hasOwnProperty(el.id)) {
hashTable[el.id] = [];
}
hashTable[el.id].push(el.email);
});
return hashTable;
}
Result should be:
{
1: ['bin#example.com', 'foo#example.com' ],
2: ['sho#example.com']
}
Hope this helped.
Not sure if title is formulated correct, but I have a JS object that looks like:
parent:{
children:[
{
id: "1"
user:[
{
id: 'aa',
email:'aa#google.com'
},
{
id: 'b',
email:'bbb#google.com'
},
]
},
{
id:"2",
user: [
{
id:'aa',
email:'aa#google.com'
},
{
id:'eee',
email:'eee#google.com'
}
]
}
]
}
The object is way bigger but follows the above structure.
How would I go to get a list of topics each user is on, filtered b ID?
E.g. 'aa' participates in children 1 and 2
'b' participates in child 1
etc.
I figure it out I have to map the object but not sure how to proceed after that
Assuming, you want an object with participant as key and all topic id in an object, then you could iterate the arrays an build a property with the associated id.
var data = { project: { topics: [{ id: "1", participants: [{ id: 'aa', email: 'aa#google.com' }, { id: 'b', email: 'bbb#google.com' }, ] }, { id: "2", participants: [{ id: 'aa', email: 'aa#google.com' }, { id: 'eee', email: 'eee#google.com' }] }] } },
result = Object.create(null);
data.project.topics.forEach(function (a) {
a.participants.forEach(function (b) {
result[b.id] = result[b.id] || [];
result[b.id].push(a.id);
});
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can write a function like this one:
function findTopicByID(id) {
let findedTopic = {};
let topics = obj.project.topics;
topics.map((topic) => {
if(parseInt(topic.id) === id) findedTopic = topic;
});
return findedTopic;
}
This function return the finded topic with the corresponding id or an empty object.
You can loop the topic array and build a new resulting array of users, if a user already exist then just update the users topic list, else create a new user with name, email, and a topic list.
let result = [];
project.topics.forEach((t) => {
t.participants.forEach((p) => {
let found = result.find((r) => r.name === p.id);
if (found) {
found.topics.push(t.id);
} else {
result.push({
name: p.id,
email: p.email,
topics: [t.id]
});
}
});
});
so now when you have the resulting array, you can just find a user and get which topics she participates in
let aa = result.find((r) => r.name === 'aa');
console.log(aa.topics);
I get json from client side which is nested, I want to faltten it and make the children object keys, preferably using underscore.js.
For example that is my json:
var data = {
or:[
{
dealershipCompany : 11
},
{
authType: 'google'
}],
and: [
{
or: [
{
firstName: {'contains': 'search'}
},
{
lastName: {'contains': 'search'}
},
{
email: {'contains': 'search'}
}]
}]
};
I want to remove both 'or' & 'and'
and when I get the object keys using Object.keys(data) I get
['0','1','2','3','4','5']
but I want it to be like this
['dealershipCompany', 'authType', 'firstName', 'lastName','email']
I tried several times to flatten it by myself but always object keys get numbered
Here the link of jsFiddle
This should work:
var data = {
or:[
{ dealershipCompany : 11 },
{ authType: 'google' }
],
and: [ {
or: [
{ firstName: {'contains': 'search'} },
{ lastName: {'contains': 'search'} },
{ email: {'contains': 'search'} }
]
}]
};
function getOnlyObjects(data) {
var result = [];
if (Array.isArray(data)) {
data.forEach(function(item) {
result = result.concat(
getOnlyObjects(item)
);
});
}
else {
Object.keys(data).forEach(function(key) {
if (Array.isArray(data[key])) {
result = result.concat(
getOnlyObjects(data[key])
);
}
else {
result = result.concat(data);
}
});
}
return result;
}
function getData(data) {
return getOnlyObjects(data).map(function(item) {
return Object.keys(item)[0];
});
}
console.log(getData(data));
Outputs:
["dealershipCompany", "authType", "firstName", "lastName", "email"]
When you use Object.keys over array, you will get indexes, hence you were getting ['0','1','2','3','4','5'].
Edit 1
Have migrated === 'and', === 'or' to an array exceptionList. You can add further keys that you need to filter. This will keep filtering manageable and condition clean.
Code
JSFiddle
var data = {
or: [{
dealershipCompany: 11
}, {
authType: 'google'
}],
and: [{
or: [{
firstName: {
'contains': 'search'
}
}, {
lastName: {
'contains': 'search'
}
}, {
email: {
'contains': 'search'
}
}, ]
}]
};
var result = [];
// You can add further keys that you want to filter
var exceptionList = ["and", "or"];
function getKeys(obj) {
var _keys = Object.keys(obj);
_keys.forEach(function(key) {
// Check if key is either,`and`, `or`, or an index of array.
if (exceptionList.indexOf(key) >=0 || !isNaN(key)) {
getKeys(obj[key]);
} else {
result.push(key);
}
});
}
getKeys(data);
console.log(result)