javascript - pushing new property to objects that are in an array - javascript

I got an array person containing many objects that look like this:
const person = [
{ first: 'firstName', last: 'lastName', year: 1439, passed: 1495 },
...
]
I have counted how many years the person lived:
const oldest = person.map(x => x.passed - x.year);
Got new array with the years for every person.
Now I would like to push this calculated year as a new property age to each person object in this array.
Can you help me out?

You could add a new property
person.forEach(p => p.lifetime = p.passed - p.year);
Or map a new array of objects
persons = person.map(p => ({ ...p, lifetime: p.passed - p.year });

You can set the property directly by assigning value To it like this
Person[0].age = oldest[0]:
You can loop like this.

You can use array.forEach, which will iterate through the same array and you can create a new property to the same array.
If you want get a new array you can use array.map, which will create a new array.
I hope this will solve the issue.
const person = [
{ first: 'firstName', last: 'lastName', year: 1439, passed: 1489 },
{ first: 'secondName', last: 'lastName', year: 1499, passed: 1590 },
{ first: 'thirdName', last: 'lastName', year: 1539, passed: 1570 },
{ first: 'fourthName', last: 'lastName', year: 1993, passed: 2018 },
]
person.forEach(obj => obj["age"] = obj.passed - obj.year)
console.log("same array with added age property", person)

Since both arrays person and oldest have the same length, you can just iterate over either, construct new objects with age properties from the elements of both arrays at the same index and push them to a result array.
const person = [
{ first: 'firstName', last: 'lastName', year: 1439, passed: 1495 }
];
const oldest = person.map(x => x.passed - x.year);
const result = [];
person.forEach(({first, last, year, passed}, i) => result.push({first, last, year, passed, age: oldest[i]}));
console.log(result);
Given a zip function (which unfortunately is not yet standard JavaScript), you could also shorten this to:
zip(person, oldest).map(([{first last, year, passed}, age]) => ({first, last, year, passed, age}));

Related

Add two variables together/find

It works except when the subject unless the subject is the same name. Then I get the first date to the second subject that is the same.
I can't change the array since it's through API. However can I make so somehow if the first date is already set on math, then it should add the second date to second subject? Now the second subject get's the first date
var subjects = [
{ name: "math" }, //The first
{ name: "sports" },
{ name: "math" }, //The second
{ name: "art" },
];
var subjectdates = [
{ name: "math", year: 2017 }, //first date
{ name: "sports", year: 2018 },
{ name: "math", year: 2019 }, //second date
{ name: "art", year: 2020 },
];
const addDates = subjects.map((classes) => ({
subject: classes,
end_subject_date: subjectdates.find((item) => classes.name == item.name),
}));
console.log(addDates);
Using Array#reduce on subjectdates, construct a Map where the key is the name and the value is a list of the elements of this name.
Then, in the loop, to get the end_subject_date, you can use Map#get to get the list of elements of this name, and Array#shift to get and remove the first element:
const
subjects = [ {name:"math"}, {name:"sports"}, {name:"math"}, {name:"art"} ],
subjectdates = [ {name:"math",year:2017}, {name:"sports",year:2018}, {name:"math",year:2019}, {name:"art",year:2020} ];
const subjectDatesMap = subjectdates.reduce((map, item) =>
map.set(
item.name,
[...(map.get(item.name) || []), item]
)
, new Map);
const addDates = subjects.map(classes => ({
subject: classes,
end_subject_date: (subjectDatesMap.get(classes.name) || []).shift()
}));
console.log(addDates);
If you have the same keys in arrays:
Sort array by keys:
subjects = subjects.sort((a,b)=>a.name>b.name?1:-1);
subjectdates = subjectdates.sort((a,b)=>a.name>b.name?1:-1);
Insert values by index:
const result = subjects.map((s, i)=>
({ subject:s.name, end_subject_date:subjectdates[i].year}) );

How to rest only one value of an object inside an array of Objects

I have an array of objects. All of the objects have these keys and values :
const arr=[ { name: 'beer', amount: 50, price: 50 }]
function changeValue(){
// here I would like to receive back an array with the same object keys and values except amount.
// arr.amount should be 0
}
<button onclick='changeValue()'> Reset Amount </button>
How can I get back the same exact array with same objects, except the amount should be 0 for each one? I think this can be possible be done with the spread operator.
You can use rest parameters.
const arr=[ { name: 'beer', amount: 100, price: 50 }, { name: 'test', amount: 50, price: 10 }];
const res = arr.map(({amount, ...rest})=>({...rest, amount: 0}));
console.log(res);
You need to map the original array
function changeValue(something){
return arr.map( it => ({
...it,
amount: something
}))
}
You may also want to filter the it based on some criteria

Javascript arrays and objects: Get differences and merge them

So I have this scenario where I have a client-app which sends data (array of objects) to a server which then forwards the data to other clients connected to this server.
In the client-app, the data is constantly changing, meaning: Values change, new objects inside the array pop up, objects being removed, and so on ...
Now I want the other clients to always receive the latest data. And because I dont want the client-app to just push the whole new data to the server which then forwards the whole new data to the other clients, I decided to let the client-app only push the changes (using this library: https://www.npmjs.com/package/deep-object-diff).
The other clients then receive an array of objects with only the data that has actually changed and because they know the previous data array, I want them to "merge" the array of changes with the old data object.
My actual problem is the merging. I dont know how to properly do this. Especially if I have an array of objects without any key for the objects.
So my data looks something like this:
let data = [
{
name: 'Peter',
age: 26,
sID: 546589995544
},
{
name: 'John',
age: 33,
sID: 554589525469
}
];
Actually there's much more but well, thats the structure.
So if the diff library says, this are the changes:
let changes = {
{
age: 34,
sID: 554589525469
}
};
(notice that I now have an object of objects, not an array of objects. Thats what the diff-library returns)
I want the merged object to be
[
{
name: 'Peter',
age: 26,
sID: 546589995544
},
{
name: 'John',
age: 34,
sID: 554589525469
}
];
(John is now one year older)
So I totally believe that this would be much easier if I had a key to the objects as an identifier, but still I think there has to be a solution for exactly this scenario. And as you can see, the sID property could act as an identifier, its just not a key.
I would apprectiate if someone could point out how to do it in both cases (with and without a specific key for the objects)
You can use .find() to find the object within the array where values should be changed, Object.assign() to set the values
let data = [{
name: 'Peter',
age: 26,
sID: 546589995544
},
{
name: 'John',
age: 33,
sID: 554589525469
}
];
let changes = [{
age: 34,
sID: 554589525469
}];
for (let prop of changes) {
let {sID} = prop;
Object.assign(data.find(({sID: id}) => id === sID), prop)
}
console.log(data);
You could use a sId Map for fast lookup:
const byId = new Map( data.map( el => [el.sID, el]));
Then for every change we can find if the obj already exists, if not we add it, if yes we mutate:
changes.forEach(change => {
const res = byId.get( change.sID );
if( res ){
Object.assign( res, change);
}else{
data.push(change);
byId.set( change.sID, change);
}
});
Using lodash, you can accomplish this with unionBy :
const newData = _.unionBy(changes, data, 'sID'); // values from changes will be picked
This will pick objects from both the arrays based on sID and combine them into a single array.
If your changes data is object of objects , you can use Object.values to loop data value and merge same id data by Object.assign
let data = [
{
name: 'Peter',
age: 26,
sID: 546589995544
},
{
name: 'John',
age: 33,
sID: 554589525469
}
];
let changes = {
0:
{
age: 34,
sID: 554589525469
}
};
data.filter((idx,i)=>
Object.values(changes).forEach((index)=>
(index.sID == idx.sID) ? Object.assign(data[i],index) : null
)
);
console.log(data);

How do you create Object of Arrays in Javascript

I spent more time on this than I would like to admit. I have trouble constructing an object filled with an array.
I would like my data to look like this:
items={
{
'2012-05-22': [{text: 'item 1 - any js object'}],
'2012-05-23': [{text: 'item 2 - any js object'}],
'2012-05-24': [],
'2012-05-25': [{text: 'item 3 - any js object'},{text: 'any js object'}],
}
}
I am making a database call and the data I receive looks like this:
Object {start: "08:00:00", end: "09:00:00", full_name: "Tomomi", date: "2017-06-08", Barber_id: "1"…}
The data I am interested in is the full_name value and the date value.
This is what I have attempted:
let newItems = {};
axios.post(endpoint, {lookup: day.dateString}).then((customerData) => {
customerData.data.forEach((val,key)=>{
newItems = {[val.date]:[]};
newItems[val.date].push({name:val.full_name});
console.log(newItems);
})
}
It looks like this:
Object {2017-06-08: Array(1)}
2017-06-08
:
Array(1)
This is very close, but the problem is that my code is overwriting my data.
I am trying to create this dynamically:
'2012-05-25': [{text: 'item 3 - any js object'},{text: 'any js object'}],
So that each date can have many users. Hopefully, this makes sense.
Thanks for any help.
The function expression you pass to forEach has this as the first line:
newItems = {[val.date]:[]};
This resets the newItems object to an object with one date:name pair. You really want something more like:
newItems[val.date]?newItems[val.date].push({name:val.full_name}):newItems[val.date]=[];
var byDate = {}; // Object to store received data by-date
function addIntoByDate( obj ) {
byDate[obj.date] = byDate[obj.date] || [];
byDate[obj.date].push( obj );
}
// Simulate adding server data one by one
addIntoByDate( {date: "2017-06-08", full_name: "Cat", text:"Foo!!"} ); // < SAME DATE
addIntoByDate( {date: "2016-05-23", full_name: "Dog", text:"Bar"} );
addIntoByDate( {date: "2017-06-08", full_name: "Bug", text:"Baz..."} ); // < SAME DATE
// test
console.dir(byDate);
You can use object destructuring, computed property and Object.assign()
const newItems = {};
const data = [
{
start: "08:00:00"
, end: "09:00:00"
, full_name: "Tomomi"
, date: "2017-06-08"
, Barber_id: "1"
}
];
data.forEach(({date, full_name}) =>
Object.assign(newItems, {[date]: [{/* text: */ full_name}]}));
console.log(newItems);

Create new array from de-duped dates

I'm working through gathering information from multiple arrays but I've hit a stumbling block. I need to be able to determine how many days were spent in each city. The trouble is I can't figure out a way to count time entries that span a single day as 1 day. In the below the first two San Diego entries should result in a single day since both logs happened within the same day.
timeLogs = [
{'city':'San Diego','date':'2017-03-21T18:52:00.984Z'},
{'city':'San Diego','date':'2017-03-21T12:13:00.984Z'},
{'city':'San Diego','date':'2017-03-19T11:02:00.984Z'},
{'city':'Boulder','date':'2017-02-12T11:29:00.984Z'}
]
What I'm after is the following resulting array based on the above:
daysPerCity = [
{'San Diego':'2'},
{'Boulder':'1'}
]
Currently I'm working on a loop which coverts the dates to strings and then checks for equality, if the same I'm trying to not increment the city in the new array but I'm stuck when it hits the very first instance of a city...
You can use Array methods like reduce and map to build an object containing unique days grouped by city, and then use Object.keys(...).length to get the number of distinct days.
var timeLogs = [
{ city: 'San Diego', date: '2017-03-21T18:52:00.984Z' },
{ city: 'San Diego', date: '2017-03-21T12:13:00.984Z' },
{ city: 'San Diego', date: '2017-03-19T11:02:00.984Z' },
{ city: 'Boulder', date: '2017-02-12T11:29:00.984Z' }
]
var daysPerCity = timeLogs.reduce(function (map, e) {
(map[e.city] = map[e.city] || {})[e.date.slice(0, 10)] = true
return map
}, {})
Object.keys(daysPerCity).forEach(function (k) {
this[k] = Object.keys(this[k]).length
}, daysPerCity)
console.log(daysPerCity)
You could use this ES6 code:
const timeLogs = [
{'city':'San Diego','date':'2017-03-21T18:52:00.984Z'},
{'city':'San Diego','date':'2017-03-21T12:13:00.984Z'},
{'city':'San Diego','date':'2017-03-19T11:02:00.984Z'},
{'city':'Boulder','date':'2017-02-12T11:29:00.984Z'}
];
const result = Object.assign({}, ...Array.from(
timeLogs.reduce( (acc, {city, date}) => {
(acc.get(city) || acc.set(city, new Set).get(city))
.add(date.substr(0, 10));
return acc;
}, new Map),
([city, days]) => ({ [city]: days.size })
));
console.log(result);

Categories

Resources