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);
Related
I have an array
const dataCheck = ["Rohit","Ravi"];
I have another array of object
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
I want to check if any value in dataCheck is present in the userData and then return a new array with the below data
const newData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit", status: "present" },
{ name: "Ravi", status: "present" },
];
I tried to do something using loops but not getting the expected results
const dataCheck = ["Rohit", "Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" }
];
let newDataValue = {};
let newData = [];
userData.forEach((user) => {
const name = user.name;
dataCheck.forEach((userName) => {
if (name === userName) {
newDataValue = {
name: name,
status: "present"
};
} else {
newDataValue = {
name: name
};
}
newData.push(newDataValue);
});
});
console.log(newData);
My trial gives me repeated results multiple results which is just duplicates
You should use map() and a Set.
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
const set = new Set(dataCheck);
const output = userData.map(data => set.has(data.name) ? ({...data, status: "present"}): data)
console.log(output)
.as-console-wrapper { max-height: 100% !important; top: 0; }
A Set allows for lookups in O(1) time and therefore this algorithm works in O(n) time. If you would use the array for lookups (e.g. using indcludes(), find() etc.) the runtime would be O(n²). Although this will certainly not matter at all for such small arrays, it will become more relevant the larger the array gets.
map() is used here because you want a 1:1 mapping of inputs to outputs. The only thing to determine then is, what the output should be. It is either the input, if the value is not in the Set, or it is the input extended by one property status set to "present". You can check for the presence in a Set using the has() method and can use the ternary operator ? to make the decision which case it is.
const dataCheck = ["Rohit", "Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
// map through every object and check if name property
// exists in data check with help of filter.
// if it exists the length of filter should be 1 so
// you should return { name: el.name, status: "present" } else
// return { name: el.name }
let newData = userData.map((el) => {
if (dataCheck.filter((name) => name === el.name).length > 0) {
return { name: el.name, status: "present" };
} else {
return { name: el.name };
}
});
console.log("newdata: ", newData);
A better approach would be to use map over userData array, find for matching element in dataCheck, if found return matching element + a status key or just return the found element as it is.
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
const getUpdatedObject = () => {
return userData.map(userData => {
const userDetail = dataCheck.find(data => userData.name === data);
if(userDetail) return {userDetail, status:"present"}
else return {...userData}
});
}
console.log(getUpdatedObject())
Working fiddle
Loop through userData, check if name is includes in dataCheck. If true add status 'present'.
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
for (let user of userData) {
if(dataCheck.includes(user.name)) {
user.status = 'present'
}
}
console.log(userData)
You are seeing repeated results due to the second loop dataCheck.forEach((userName) => { as every loop of dataCheck will fire the if/else statement and add something to the final array. However many values you add to dataCheck will be however many duplicates you get.
Only need to loop through one array and check if the value is in the other array so no duplicates get added.
const dataCheck = ["Rohit", "Ravi"];
const userData = [{ name: "Sagar" }, { name: "Vishal" }, { name: "Rohit" }, { name: "Ravi" }];
let newDataValue = {};
let newData = [];
// loop thru the users
userData.forEach((user) => {
// set the user
const name = user.name;
// check if in array
if (dataCheck.indexOf(name) >= 0) {
newDataValue = {
name: name,
status: "present",
};
}
// not in array
else {
newDataValue = {
name: name,
};
}
newData.push(newDataValue);
});
console.log(newData);
So you will do like this :
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
const newUserData = userData.map( user => {
dataCheck.forEach( data => {
if( data === user.name )
user.status = "present";
});
return user;
} );
console.log( newUserData );
I have two different response from API. Below response contain lineId and Name.
this.lines = [
{
lineId: "R_X002_ACCESS"
localName: "ACCESS"
name: "ACCESS"
},
{
lineId: "R_X00R_X002_BIB2_ACCESS"
localName: "BIB"
name: "BIB"
},
{
lineId: "R_X002_KNORR"
localName: "Knorr"
name: "Knorr"
},
{
lineId: "R_X002_POWDER"
localName: "Powder"
name: "Powder"
},
];
This response is for processData function, Here i wanted to search name from this.lines api response based on lineId of item object and if matches then need to push Name
item = {
lineId: "R_X002_POWDER"
},
{
lineId: "R_X00R_X002_BIB2_ACCESS,R_X002_ACCESS"
},
{
lineId: "R_X002_POWDER"
};
Now in below code , i am searching name based on lineId from this.lines api response
and if it matches then trying to push inside plist array.
Below is my code, here i am passing api response and preparing array based on some condition.
I tried below code inside processData function, but it is not working for comma seprated valuesand also not pushing to proper plist array.
var lineName = this.lines.filter(function(line) {
if(line.lineId === item.lineId){
return line.name;
}
});
processData(data: any) {
let mappedData = [];
for(const item of data){
console.log(item,"item");
var lineName = this.lines.filter(function(line) {
if(line.lineId === item.lineId){
return line.name;
}
});
const mitem = mappedData.find(obj => obj.makeLineName == item.makeLineName);
if(mitem){
mitem['plist'].push(item);
} else {
let newItem = item;
newItem['plist'] = [ item ];
mappedData.push(newItem);
}
}
return mappedData;
}
Expected output
lineId: "R_X002_POWDER",
name: "Powder"
},
{
lineId: "R_X00R_X002_BIB2_ACCESS,R_X002_ACCESS",
name: "BIB","ACCESS"
},
{
lineId: "R_X002_KNORR",
name: "Knorr"
};
I think because of lineId returned to you, instead of checking lineId equality you should check if the incoming lineId includes your lineId.
in your code: instead of line.lineId === item.lineId check this: (item.lineId).includes(line.lineId)
maybe it works...
Does this work for you(mapNames function)...
const lines = [
{
lineId: "R_X002_ACCESS",
localName: "ACCESS",
name: "ACCESS"
},
{
lineId: "R_X00R_X002_BIB2_ACCESS",
localName: "BIB",
name: "BIB"
},
{
lineId: "R_X002_KNORR",
localName: "Knorr",
name: "Knorr"
},
{
lineId: "R_X002_POWDER",
localName: "Powder",
name: "Powder"
},
];
const items = [
{
lineId: "R_X002_POWDER"
},
{
lineId: "R_X00R_X002_BIB2_ACCESS,R_X002_ACCESS"
},
{
lineId: "R_X002_POWDER"
}
];
function mapNames(lines, items) {
const mappedLines = {};
lines.forEach(lineItem => {
if (!mappedLines[lineItem.lineId]) {
mappedLines[lineItem.lineId] = lineItem;
}
});
const mappedItems = items
.map(item => {
return {
lineId: item.lineId,
name: item.lineId.split(",")
.map(lineItem => mappedLines[lineItem].name || "")
.filter(x => x)
.join(",")
};
});
return mappedItems;
}
console.log("Mapped Names:\n", mapNames(lines, items));
I have a problem I can't get my head around. If I am looking for an object with a certain ID in a possibly infinite data structure, how can I loop through it until I find the object I need and return that object?
If this is what my data looks like, how can I get the object with id === 3 ?
{
id: 0,
categories: [
{
id: 1,
categories: [
{
id: 2,
categories: [ ... ]
},
{
id: 3,
categories: [ ... ]
},
{
id: 4,
categories: [ ... ]
},
]
}
]
}
I tried the following:
findCategory = (categoryID, notesCategory) => {
if (notesCategory.id === categoryID) {
return notesCategory;
}
for (let i = 0; i < notesCategory.categories.length; i += 1) {
return findCategory(categoryID, notesCategory.categories[i]);
}
return null;
};
But that doesn't get ever get to id === 3. It checks the object with id: 2 and then returns null. It never gets to the object with id: 3.
Here is a JSbin: https://jsbin.com/roloqedeya/1/edit?js,console
Here is the case. when you go in to the first iteration of 'for' loop, because of the return call, the execution is go out from the function. you can check it by using an console.log to print the current object in the begin of your function.
try this
function find(obj, id) {
if(obj.id === id) {
console.log(obj) // just for testing. you can remove this line
return obj
} else {
for(var i = 0; i < obj.categories.length; i++) {
var res = find(obj.categories[i], id);
if(res) return res;
}
}
}
hope this will help you. thanks
You need to store the intermediate result and return only of the object is found.
function findCategory(object, id) {
var temp;
if (object.id === id) {
return object;
}
object.categories.some(o => temp = findCategory(o, id));
return temp;
}
var data = { id: 0, categories: [{ id: 1, categories: [{ id: 2, categories: [] }, { id: 3, categories: [] }, { id: 4, categories: [] }] }] }
result = findCategory(data, 3);
console.log(result);
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;}
I need to split an Array by its objects subvalue (type).
Let's assume I have following array:
[
{id:1,name:"John",information: { type :"employee"}},
{id:2,name:"Charles",information: { type :"employee"}},
{id:3,name:"Emma",information: { type :"ceo"}},
{id:4,name:"Jane",information: { type :"customer"}}
]
and I want to split the object by information.type so my final result looks like:
[
{
type:"employee",
persons:
[
{id:1,name:"John",information: { ... }},
{id:2,name:"Charles",information: { ... }
]
},
{
type:"ceo",
persons:
[
{id:3,name:"Emma",information: { ... }}
]
},
{
type:"customer",
persons:
[
{id:4,name:"Jane",information: { ... }}
]
},
]
Underscore is available at my Project. Any other helper library could be included.
Of course I could loop through the array and implement my own logic, but i was looking for cleaner solution.
This returns exactly what you want:
_.pairs(_.groupBy(originalArray, v => v.information.type)).map(p => ({type: p[0], persons: p[1]}))
A solution in plain Javascript with a temporary object for the groups.
var array = [{ id: 1, name: "John", information: { type: "employee" } }, { id: 2, name: "Charles", information: { type: "employee" } }, { id: 3, name: "Emma", information: { type: "ceo" } }, { id: 4, name: "Jane", information: { type: "customer" } }],
result = [];
array.forEach(function (a) {
var type = a.information.type;
if (!this[type]) {
this[type] = { type: type, persons: [] };
result.push(this[type]);
}
this[type].persons.push({ id: a.id, name: a.name });
}, {});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
You could use the groupBy function of underscore.js:
var empList = [
{id:1,name:"John",information: { type :"employee"}},
{id:2,name:"Charles",information: { type :"employee"}},
{id:3,name:"Emma",information: { type :"ceo"}},
{id:4,name:"Jane",information: { type :"customer"}}
];
_.groupBy(empList, function(emp){ return emp.information.type; });