How to update the array by changing one of the objects?
This will be my array code
this.datas = [
{
index: 1,
name: 'Tony',
status: 'Absent',
reason: null
},
{
index: 2,
name: 'Chris',
status: 'Present',
reason: null
},
];
So now i want to write a function to update the reason like {reason: any reason} which from the index 1, index 2 remain the same.
So Far i had tried these
setReason = reason => {
let data = [...this.state.nameList];
let ind = data.findIndex(el => el.index === 'number');
data[ind] = { ...data[ind], reason: reason };
this.setState({
nameList: data
});
};
To update a single object data of an array
You need to first know the index of the object in the array which you want to update
eg Want to update first object of array
this.datas[0].reason = 'My custom reason';
Now you want to update the object of an array by finding the object in array you have to add a loop in it
eg: Update reason where name = Chris
for(i=0; i<this.datas.length; i++){
if(this.datas[i].name=='Chris'){
this.datas[i].reason = 'My custom reason';
break;
}
}
you can use map function on array.
let data = [
{
index: 1,
name: 'Tony',
status: 'Absent',
reason: null
},
{
index: 2,
name: 'Chris',
status: 'Present',
reason: null
},
];
data = data.map(obj=>{
return{
...obj,
reason: 'any reason',
}
})
You can use of in the for loop and update the property value in an array, this is the working solution of your question.
var datas = [
{
index: 1,
name: 'Tony',
status: 'Absent',
reason: null
},
{
index: 2,
name: 'Chris',
status: 'Present',
reason: null
},
];
for(data of datas){
data["reason"] = "any reason";
}
console.log(datas);
Try this
var datas = [
{
index: 1,
name: 'Tony',
status: 'Absent',
reason: null
},
{
index: 2,
name: 'Chris',
status: 'Present',
reason: null
},
];
datas.map(data=> data.reason ="my reason");
console.log(datas)
Related
I have an array of objects that looks like this:
const arr = [
{id: 123, message: { user_id: 4, text: 'fish'}}
{id: 456, message: { user_id: 4, text: 'cow'}}
{id: 789, message: { user_id: 5, text: 'chicken'}}
{id: 010, message: { user_id: 5, text: 'turkey'}}
]
I want to return the first item in the array where the message.user_id is unique. I'm expecting a result like this:
newArr = [
{id: 123, message: { user_id: 4, text: 'fish'}}
{id: 789, message: { user_id: 5, text: 'chicken'}}
]
I can't seem to find any solution for this. I'm dealing with dynamic data so I can't exactly hardcode the user_id and the array I'm working with contains a lot of elements so I'm trying as much as possible to avoid looping through.
Please what's the best way for me to achieve this?
Here is another similar solution but with a bit modified syntax, I hope this will be helpful:
const arr = [
{id: 123, message: { user_id: 4, text: 'fish'}},
{id: 456, message: { user_id: 4, text: 'cow'}},
{id: 789, message: { user_id: 5, text: 'chicken'}},
{id: 010, message: { user_id: 5, text: 'turkey'}}
];
const uniqueResult = (Object.values(arr.reduce(function(acc, item) {
if (!acc[item.message.user_id]) {
acc[item.message.user_id] = item;
}
return acc;
}, {})));
console.log(uniqueResult);
Create a dictionary/object.
Iterate through the array and check if
the id is a key in it
2.1 If yes, skip
2.2 If not:
Add the row to the output
Add the user_id to the dictionary.
const arr = [
{id: 123, message: { user_id: 4, text: 'fish'}},
{id: 456, message: { user_id: 4, text: 'cow'}},
{id: 789, message: { user_id: 5, text: 'chicken'}},
{id: 010, message: { user_id: 5, text: 'turkey'}}
]
const userIDs = {}
const output = arr.reduce((acc, item) => {
const user_id = item.message.user_id
if (userIDs[user_id]) return acc
acc.push(item)
userIDs[user_id] = true;
return acc
},[])
console.log(output)
I have the following objects
Person {
name: string
birthday: Date
lifeEvents: LifeEvent[]
}
LifeEvent {
eventId: number
message: string
comments: string
}
As the data comes in chunks, I will have an array of Person with one object that has name and birthday with values but lifeEvents is empty (Think of this one like a parent object.)
All other objects won't have birthday and name populated and will have only one LifeEvent with either eventId and message with values or eventId and comments
Within that array, I need to get the parent object, which has name and birthday with values, then get all lifeEvents from the remaining objects, merge all items that contains same eventId into a LifeEvent then push it to lifeEvents of the parent.
I have tried array.reduce, array.map but can't figure out a way of combining those objects into one.
My output should be only one Person with all lifeEvents merged by eventId
Sample data:
let results = [
{
name: 'Test1',
birthday: '2022-06-14',
lifeEvents: null
},
{
name: null,
birthday: null,
lifeEvents: [
{
eventId: 1,
message: 'First event',
comments: null
}
]
},
{
name: null,
birthday: null,
lifeEvents: [
{
eventId: 2,
message: 'Second event',
comments: null
}
]
},
{
name: null
birthday: null
lifeEvents: [
{
eventId: 1,
message: null,
comments: 'First event comment'
}
]
},
{
name: null
birthday: null
lifeEvents: [
{
eventId: 2,
message: null,
comments: 'Second event comment'
}
]
},
]
Appreciate any help.
Premise: The data structure you are using is wrong, you should try to use arrays with homogenous models.
That said I used a reduce method, with a condition to treat the first element in a different way from the other ones.
Last thing, you said merge lifeEvents, I assume you meant to overwrite the nullish values for events with same ids, if you want to overwrite all values then you can omit the merge utility function I wrote.
let results = [{
name: 'Test1',
birthday: '2022-06-14',
lifeEvents: null,
},
{
name: null,
birthday: null,
lifeEvents: [{
eventId: 1,
message: 'First event',
comments: null,
}, ],
},
{
name: null,
birthday: null,
lifeEvents: [{
eventId: 2,
message: 'Second event',
comments: null,
}, ],
},
{
name: null,
birthday: null,
lifeEvents: [{
eventId: 1,
message: null,
comments: 'First event comment',
}, ],
},
{
name: null,
birthday: null,
lifeEvents: [{
eventId: 2,
message: null,
comments: 'Second event comment',
}, ],
},
];
const merge = (o1, o2) => {
const r = {...o1}
Object.keys(o1).forEach(k => r[k] = o2[k] || o1[k])
return r
}
const r = results.reduce((o, curr, i) => {
if (i === 0) {
return { ...o,
lifeEvents: []
};
} else {
const currentEvent = curr.lifeEvents[0]
const idx = o.lifeEvents.findIndex((_o) => _o.eventId === currentEvent.eventId);
if (idx !== -1) return { ...o,
lifeEvents: o.lifeEvents.map((_o, i) => i === idx ? merge(_o, currentEvent) : _o)
}
else return { ...o,
lifeEvents: [...o.lifeEvents, currentEvent]
}
}
}, results[0]);
console.log("RESULT:", r);
The following produces the requested result based on examples provided:
let results = [
{
name: 'Test1',
birthday: '2022-06-14',
lifeEvents: null
},
{
name: null,
birthday: null,
lifeEvents: [
{
eventId: 1,
message: 'First event',
comments: null
}
]
},
{
name: null,
birthday: null,
lifeEvents: [
{
eventId: 2,
message: 'Second event',
comments: null
}
]
},
{
name: null,
birthday: null,
lifeEvents: [
{
eventId: 1,
message: null,
comments: 'First event comment'
}
]
},
{
name: null,
birthday: null,
lifeEvents: [
{
eventId: 2,
message: null,
comments: 'Second event comment'
}
]
},
];
// extract parent
const parentResult = results.find((result) => result.name);
// generate unique events from sibling entities
const uniqueEvents = new Map();
results.forEach((result) => result.lifeEvents?.forEach(
(lifeEvent) => {
if (uniqueEvents.has(lifeEvent.eventId)) {
updateEvent(lifeEvent);
} else {
uniqueEvents.set(lifeEvent.eventId, { eventId: lifeEvent.eventId, message: lifeEvent.message, comments: lifeEvent.comments});
}
})
);
// function to update event that is already stored in uniqueEvents
function updateEvent(lifeEvent) {
const existingLifeEvent = uniqueEvents.get(lifeEvent.eventId);
if (lifeEvent.message) existingLifeEvent.message = lifeEvent.message;
if (lifeEvent.comments) {
if (existingLifeEvent.comments) {
existingLifeEvent.comments.concat(lifeEvent.comments)
} else {
existingLifeEvent.comments = lifeEvent.comments;
}
}
}
// populate lifeEvents inside the parentResult
parentResult.lifeEvents = [];
uniqueEvents.forEach((uniqueId) => {
parentResult.lifeEvents.push(uniqueId);
});
console.log(parentResult);
I have an array of objects like this:
const myArray = [
{
id: 1234,
name: 'foo',
status: 'OK'
},
{
id: 1235,
name: 'foo',
status: 'KO'
},
{
id: 1236,
name: 'bar',
status: 'KO'
},
{
id: 1237,
name: 'bar',
status: 'OK'
},
{
id: 1238,
name: 'baz',
status: 'KO'
}
]
and I need to filter it, keeping only one with the same name, and it should be the one with the highest id.
const expectedOutput = [
{
id: 1235,
name: 'foo',
status: 'KO'
},
{
id: 1237,
name: 'bar',
status: 'OK'
},
{
id: 1238,
name: 'baz',
status: 'KO'
}
]
I've been strugling but I can't find the best solution. Any idea?
Keep track of maxes in an object mapping names to objects:
const myArray = [
{
id: 1234,
name: 'foo',
status: 'OK'
},
{
id: 1235,
name: 'foo',
status: 'KO'
},
{
id: 1236,
name: 'bar',
status: 'KO'
},
{
id: 1237,
name: 'bar',
status: 'OK'
},
{
id: 1238,
name: 'baz',
status: 'KO'
}
];
const maxes = {};
for (const ele of myArray) {
if (!(ele.name in maxes) || ele.id > maxes[ele.name].id) {
maxes[ele.name] = ele;
}
}
const filtered = Object.values(maxes);
console.log(filtered);
.as-console-wrapper {min-height: 100%;}
You can use reduce like the following. This way it will work for both sorted and unsorted array.
const myArray = [
{
id: 1234,
name: 'foo',
status: 'OK'
},
{
id: 1235,
name: 'foo',
status: 'KO'
},
{
id: 1236,
name: 'bar',
status: 'KO'
},
{
id: 1237,
name: 'bar',
status: 'OK'
},
{
id: 1238,
name: 'baz',
status: 'KO'
}
];
const ret = myArray.reduce((acc, curr) => {
const index = acc.findIndex(item => item.name === curr.name);
if(index> -1 && acc[index].id < curr.id) {
acc[index] = curr;
} else {
acc.push(curr);
}
return acc;
}, []);
console.log(ret);
Although this will work pretty good as you have to loop through the array only once. But if you use for loop instead of reduce. It will be much faster as for loops are usually faster than map, filter, reduce etc. You can do the following for fastest result,
const myArray = [
{
id: 1234,
name: 'foo',
status: 'OK'
},
{
id: 1235,
name: 'foo',
status: 'KO'
},
{
id: 1236,
name: 'bar',
status: 'KO'
},
{
id: 1237,
name: 'bar',
status: 'OK'
},
{
id: 1238,
name: 'baz',
status: 'KO'
}
];
let ret = [];
for(let i =0;i<myArray.length; i++) {
const index = ret.findIndex(item => item.name === myArray[i].name);
if(index > -1 && ret[index].id < myArray[i].id) {
ret[index]=myArray[i];
} else {
ret.push(myArray[i]);
}
}
console.log(ret);
Since the array is already sorted by id you could use a Map object and just set each value using the name as key. Overriding the previous value if present. Note that this only matches the requirements as long as the last element with a certain name has also the highest value.
const myArray = [{id:1234,name:'foo',status:'OK'},{id:1235,name:'foo',status:'KO'},{id:1236,name:'bar',status:'KO'},{id:1237,name:'bar',status:'OK'},{id:1238,name:'baz',status:'KO'}];
const lookup = new Map();
myArray.forEach(item => lookup.set(item.name, item));
const result = Array.from(lookup.values());
console.log(result);
The order of the resulting elements is based on insertion order into the Map object. The first key inserted will be the first element of the resulting array. The second key inserted will be the second element, etc.
You could do it using Map Object.
First, create a new Map Object
Traverse the array using forEach() method.
Put name as a key into a variable named key
Check if key exists by using has(key) method in the Map Object named map
If key does not exist then set it into the Map Object by calling the set(key, value) method. In this solution, key is name and value is object.
If Key exists then get the object using get(key) method, get max id using Math.max() method, then update the object and set it into the Map Object.
const myArray = [
{
id: 1234,
name: 'foo',
status: 'OK',
},
{
id: 1235,
name: 'foo',
status: 'KO',
},
{
id: 1236,
name: 'bar',
status: 'KO',
},
{
id: 1237,
name: 'bar',
status: 'OK',
},
{
id: 1238,
name: 'baz',
status: 'KO',
},
];
const map = new Map();
myArray.forEach((x) => {
const key = x.name;
if (map.has(key))
map.set(key, { ...map.get(key), id: Math.max(map.get(key).id, x.id) });
else map.set(key, { ...x });
});
const ret = [...map.values()];
console.log(ret);
I have an array of objects and Im trying to filter by matching ids
//Vehicle is added to quote
function filterByID(item) {
return item.id === 1;
}
this.vehicle = this.data.filter(filterByID);
data is as follows:
data: [
0: {
id: 0,
name: name
},
1: {
id: 1,
name: name
},
2: {
id: 2,
name: name
}
]
Im getting an empty error when I check the vehicle part
Are you using it like this:
const data = [
{
id: 0,
name: '',
},
{
id: 1,
name: '',
},
{
id: 2,
name: '',
},
];
function filterByID(item) {
return item.id === 1;
}
console.log(data.filter(filterByID)); // output: [{ "id": 1, "name": "" }]
You don't always need to define a separate function, you can use an arrow function, as below.
const data = [{
id: 0,
name: name
},
{
id: 1,
name: name
},
{
id: 2,
name: name
}
]
const vehicle = data.filter(item => item.id === 1);
console.log(vehicle);
This works fine in pure JS, it looks like it might be an issue with the lifecycle or state of your application. Use console.log to make sure that this.data is what you expect it to be
This is my json object:
{
id: 3,
cno: 103,
username: 'basha',
name: 'New Complaint',
desc: 'Need bag',
storeId: [ 5, 1 ]
}
I want my expected output like this:
[
{id: 3,cno: 103,username: 'basha',name: 'New Complaint',desc: 'Need bag',storeId:5},
{id: 3,cno: 103,username: 'basha',name: 'New Complaint',desc: 'Need bag',storeId:1}
]
You are right to choose .map. Issue is, you are trying to update an object and objects are passed using reference. So all the objects will hold same id. You will have to create a copy so that you do not override value. You can use Object.assign for that.
var data = {
id: 3,
cno: 103,
username: 'basha',
name: 'New Complaint',
desc: 'Need bag',
storeId: [ 5, 1 ]
};
var result = data.storeId.map(function(id){
return Object.assign({}, data, {storeId: id});
});
console.log(result)
If you are not comfortable using ES6 features, you can check following: How do I correctly clone a JavaScript object?
You can use .map() on the array storeId and return a new object which has current value as the value of storeId.
var obj = {
id: 3,
cno: 103,
username: 'basha',
name: 'New Complaint',
desc: 'Need bag',
storeId: [ 5, 1 ]
};
var data = obj.storeId.map(el => {
let newObject = Object.assign({}, obj);
newObject.storeId = el;
return newObject;
})
console.log(data);
You can use array#map with spread syntax to create an object with all the existing property and individual storeId.
var obj = {id: 3,cno: 103,username: 'basha',name: 'New Complaint',desc: 'Need bag',storeId: [ 5, 1 ]}
result = obj.storeId.map(storeId => ({...obj, storeId}) )
console.log(result);
var data = {
id: 3,
cno: 103,
username: 'basha',
name: 'New Complaint',
desc: 'Need bag',
storeId: [ 5, 1 ]
}
var finalData = data.storeId.map(x => {
return({
id: data.id,
cno: data.cno,
username: data.username,
name: data.name,
desc: data.desc,
storeId: x
})
});
console.log(finalData);
I tried this now i got this answer correctly, is this good approach?