I have an array of objects ...
[
{
"matchID":"-LP0LKl_nR4VQf6Gxwz8",
"playerId":"YvtwVY1gsZSzI7ZQzyDTZbSwdLF3",
"points":"11",
"id":"-LP1WvT4eN1L7BLbyhJt"
},
{
"matchID":"-LP0LKl_nR4VQf6Gxwz8",
"playerId":"YabcVY1gsZSzI7ZQzyDTZbSwdLF6",
"points":"23",
"id":"-TP1WvT4eN1L7GeYyhJt"
},
{
"matchID":"-DF0LKl_nR4VQf6Gxwz7",
"playerId":"YabcVY1gsZSzI7ZQzyDTZbSwdLF6",
"points":"12",
"id":"-GH1WvT4eN1L7GeYyhJt"
},
{
"matchID":"-DF0LKl_nR4VQf6Gxwz7",
"playerId":"YvtwVY1gsZSzI7ZQzyDTZbSwdLF3",
"points":"6",
"id":"-XZ1WvR2eN1L7GeYyhJt"
}
]
I want to loop through this array and create a new array that is a basically just each playerId and their total points for all matches.
So after cycling through the above, the array would look like ..
[{"palyerId": "YabcVY1gsZSzI7ZQzyDTZbSwdLF6", "points": "35"},{"palyerId": "YvtwVY1gsZSzI7ZQzyDTZbSwdLF3", "points": "17"}]
You can use reduce() to loop thru the array. Use new Map() to group the array. And use spread operator to convert the map object into an array.
var arr = [{"matchID":"-LP0LKl_nR4VQf6Gxwz8","palyerId":"YvtwVY1gsZSzI7ZQzyDTZbSwdLF3","points":"11","id":"-LP1WvT4eN1L7BLbyhJt"},{"matchID":"-LP0LKl_nR4VQf6Gxwz8","palyerId":"YabcVY1gsZSzI7ZQzyDTZbSwdLF6","points":"23","id":"-TP1WvT4eN1L7GeYyhJt"},{"matchID":"-DF0LKl_nR4VQf6Gxwz7","palyerId":"YabcVY1gsZSzI7ZQzyDTZbSwdLF6","points":"12","id":"-GH1WvT4eN1L7GeYyhJt"},{"matchID":"-DF0LKl_nR4VQf6Gxwz7","palyerId":"YvtwVY1gsZSzI7ZQzyDTZbSwdLF3","points":"6","id":"-XZ1WvR2eN1L7GeYyhJt"}]
var result = [...arr.reduce((c, v) => {
if (!c.has(v.palyerId)) c.set(v.palyerId, {"palyerId": v.palyerId,"points": 0});
c.get(v.palyerId).points += +v.points;
return c;
}, new Map()).values()];
console.log(result);
Or you can reduce() the array into an object using the palyerId as the key. Use Object.values() to convert the object into an array.
var arr = [{"matchID":"-LP0LKl_nR4VQf6Gxwz8","palyerId":"YvtwVY1gsZSzI7ZQzyDTZbSwdLF3","points":"11","id":"-LP1WvT4eN1L7BLbyhJt"},{"matchID":"-LP0LKl_nR4VQf6Gxwz8","palyerId":"YabcVY1gsZSzI7ZQzyDTZbSwdLF6","points":"23","id":"-TP1WvT4eN1L7GeYyhJt"},{"matchID":"-DF0LKl_nR4VQf6Gxwz7","palyerId":"YabcVY1gsZSzI7ZQzyDTZbSwdLF6","points":"12","id":"-GH1WvT4eN1L7GeYyhJt"},{"matchID":"-DF0LKl_nR4VQf6Gxwz7","palyerId":"YvtwVY1gsZSzI7ZQzyDTZbSwdLF3","points":"6","id":"-XZ1WvR2eN1L7GeYyhJt"}]
var result = Object.values(arr.reduce((c, {palyerId,points}) => {
c[palyerId] = c[palyerId] || {palyerId,points: 0};
c[palyerId].points += +points;
return c;
}, {}));
console.log(result);
A non reduce version with a for loop looks like the following (again, the central idea is to group by playerId):
let data = [{
"matchID": "-LP0LKl_nR4VQf6Gxwz8",
"playerId": "YvtwVY1gsZSzI7ZQzyDTZbSwdLF3",
"points": "11",
"id": "-LP1WvT4eN1L7BLbyhJt"
},
{
"matchID": "-LP0LKl_nR4VQf6Gxwz8",
"playerId": "YabcVY1gsZSzI7ZQzyDTZbSwdLF6",
"points": "23",
"id": "-TP1WvT4eN1L7GeYyhJt"
},
{
"matchID": "-DF0LKl_nR4VQf6Gxwz7",
"playerId": "YabcVY1gsZSzI7ZQzyDTZbSwdLF6",
"points": "12",
"id": "-GH1WvT4eN1L7GeYyhJt"
},
{
"matchID": "-DF0LKl_nR4VQf6Gxwz7",
"playerId": "YvtwVY1gsZSzI7ZQzyDTZbSwdLF3",
"points": "6",
"id": "-XZ1WvR2eN1L7GeYyhJt"
}
];
var res = {};
for (let d of data) {
if (d.playerId in res) res[d.playerId].points += parseInt(d.points);
else res[d.playerId] = {playerId: d.playerId, points: parseInt(d.points)};
}
console.log(Object.values(res));
Related
What I would like to do is to process JSON data and store each object after getting out of the for loop. However, the obj gets updated every iteration, so the objectArray holds only David's information in each element in it. I would like the objArray to hold each of the processed JSON objects (screenshot below). The JSON process is to store search a userId and name and store them in the objectArray. Could someone help me figure out how I could store each object in the objectArray? Thank you in advance.
const obj = {};
var objectArray = [];
var data = [
{
"userId": "123",
"name": "John",
"phoneNumber": "123-456-6789"
},
{
"userId": "345",
"name": "Summer",
"phoneNumber": "535-631-9742"
},
{
"userId" : "789",
"name": "David",
"phoneNumber": "633-753-1352"
}
]
var dataLen = data.length;
var people = data;
createKeyValue = ((key, value) => {
var temp = {};
temp["value"] = value;
obj[key] = temp;
});
while (dataLen > 0) {
for (let [key, value] of Object.entries(data[0])) {
switch(key) {
case 'userId':
createKeyValue(key, value);
break;
case 'name':
createKeyValue(key, value);
break;
default:
}
}
objectArray.push(obj);
data.shift();
dataLen -= 1;
}
You can do this using a simple forEach() loop to create and push new objects to the objArray array.
const data = [
{
"userId": "123",
"name": "John",
"phoneNumber": "123-456-6789"
},
{
"userId": "345",
"name": "Summer",
"phoneNumber": "535-631-9742"
},
{
"userId": "789",
"name": "David",
"phoneNumber": "633-753-1352"
}
];
let objArray = [];
data.forEach(person => {
objArray.push({
userId: { value: person.userId },
name: { value: person.name }
});
});
console.log(objArray);
The error you're seeing is because of a concept in JavaScript (and programming in general) known as "passing by reference."
Objects in JS, instead of being passed as whole groups of data, are passed around as addresses to where that data is stored. This saves a lot of overhead, since objects can become quite large.
In your case however, you're running into one of the ways it can trip you up. Since obj is really getting passed by reference instead of value, you're really .pushing 3 copies of the same address (of obj) onto objectArray rather than 3 distinct sets of data.
A better approach to this problem would be using a JS Array function called map(). This function is probably best explained by MDN:
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
You can use it on your data array like this:
var objectArray = [];
var data = [{
"userId": "123",
"name": "John",
"phoneNumber": "123-456-6789"
},
{
"userId": "345",
"name": "Summer",
"phoneNumber": "535-631-9742"
},
{
"userId": "789",
"name": "David",
"phoneNumber": "633-753-1352"
}
]
objectArray = data.map(dataEl => ({
userId: {
value: dataEl.userId,
},
name: {
value: dataEl.name,
},
}));
console.log(objectArray);
.as-console-wrapper {
max-height: 100% !important;
}
As said by our friends Kevin B and Zcoop98, its more appropriate to use forEach function, not map function:
data.forEach(elem => {
objectArray.push({
userId: { value: elem.userId },
name: { value: elem.name }
});
})
I am trying to loop through a following nested object and get an output as below:
const preference = {
"ethnicity": {
"value": "Gurung",
"rank": 1
},
"occupation": {
"value": "Banker",
"rank": 2
}
}
I tried following:
let preferenceRank = {};
preference.map(pref => {
preferenceRank[pref.rank] = pref;
});
console.log(preferenceRank);
I get this error:
"TypeError: preference.map is not a function"...
Output required:
{
1: "ethnicity",
2: "occupation",
}
You can use Object.entries to get keys and values at once (as array of arrays [key, value]):
const preference = {
"ethnicity": {
"value": "Gurung",
"rank": 1
},
"occupation": {
"value": "Banker",
"rank": 2
}
}
const preferenceRank = {}
for (const [key, { rank }] of Object.entries(preference)) {
preferenceRank[rank] = key
}
console.log(preferenceRank)
(By the way, in your code it doesn't make any sense to use map there, since you are not mapping the array to anything, and you ignore the return value of map. You probably wanted forEach instead or, as I used now, a for loop.)
2021 Update
There is now an easier way widely available, using Object.fromEntries, which does the opposite of Object.entries, thereby allowing us to express the whole thing as a mapping operation:
const preferenceRank = Object.fromEntries(
Object.entries(preference).map(([key, { rank }]) => [rank, key])
)
You can use the .entries() function to map over the object.
Object.entries(preference).reduce((out, [key, value]) => {
out[value.rank] = key;
return out;
},{});
Use Object.entries() to get an array of the keys and values of the object. You can then loop over that.
Use forEach if the loop is being done for side effect rather than using the values returned by the callback function.
const preference = {
"ethnicity": {
"value": "Gurung",
"rank": 1
},
"occupation": {
"value": "Banker",
"rank": 2
}
}
let preferenceRank = {};
Object.entries(preference).forEach(([pref, {rank}]) => {
preferenceRank[rank] = pref;
});
console.log(preferenceRank);
You could map the entries and build a new object.
const
preference = { ethnicity: { value: "Gurung", rank: 1 }, occupation: { value: "Banker", rank: 2 } },
result = Object.fromEntries(Object
.entries(preference)
.map(([k, { rank }]) => [rank, k])
);
console.log(result);
This will work.
const preferenceRank = {};
Object.keys(preference).forEach((key) => {
preferenceRank[preference[key]['rank']] = preference[key]['value'];
});
console.log(preferenceRank);
You could map over the keys and add to a result-object the rank/key-objects.
const preference = {
"ethnicity": {
"value": "Gurung",
"rank": 1
},
"occupation": {
"value": "Banker",
"rank": 2
}
}
let res= {};
Object.keys(preference).map((el,key) => {
res[preference[el].rank] = el;
});
console.log(res);
map only works for arrays, you are dealing with an object, what you can is go through the keys of the objects by using
Object.keys(preference)
this will return to you the object keys in an array as the following
["ethnicity","occupation"]
then you can map through it if you want and do your code
const preference = {
"ethnicity": {
"value": "Gurung",
"rank": 1
},
"occupation": {
"value": "Banker",
"rank": 2
}
}
console.log({...Object.keys(preference)})
I have an array of dates and an array of objects. I'd like to add the dates to the array of objects as a key value pair {"Date": "10-12-18"}.
dates:
["10-12-18", "10-13-18", 10-14-18"]
data:
[
{"name":"One", "age": "4"},
{"name":"Two", "age": "5"},
{"name":"Three", "age": "9"}
]
I want something like...
[
{"name":"One", "age": "4", "Date": "10-12-18"},
....
How can I do this in TypeScript? I'm used to normal JavaSCript and can't get it right.
Something I have so far:
for (let idx of data){
data[idx].date = dates[idx]
}
Thanks!!
What's wrong with your code is that idx will be the object not the index as you are using for...of. Use a simple regular for like:
for(let idx = 0; idx < data.length; idx++) {
data[idx].date = dates[idx];
}
Or use forEach to loop one of the arrays and use the index it provides to get the value from the other array:
data.forEach((obj, i) => obj.date = dates[i]);
const result = data.map(({ name, age }, index) => ({ name, age, date: dates[index] }));
just map the array to the result.
Something like that:
let dates = ["10-12-18", "10-13-18", "10-14-18"];
let objs = [{"name":"One",
"age": "4"},
{"name":"Two",
"age": "5"},
{"name":"Three",
"age": "9"}
]
const result = objs.map((item, index) => {
item.Date = dates[index];
return item;
});
console.log(result);
In TS, you can do this like below..
var data = [{
"name": "One",
"age": "4"
},
{
"name": "Two",
"age": "5"
},
{
"name": "Three",
"age": "9"
}
];
var dates = ["10-12-18", "10-13-18", "10-14-18"];
console.log(data.map((ob, i) => ({ ...ob,
"Date": dates[i]
})));
I have the following object:
var obj = { 2017-05-28: 76.16108625212159, 2017-02-12: 70.32183347555772, 2017-05-21: 74.21070693205216, 2017-04-23: 78.49819059107358, 2017-03-05: 73.36286201022146, 2017-04-02: 79.07588060050237, 2017-01-29: 79.07021235890568, 2017-03-26: 74.79360018220122, 2017-01-22: 71.80166785183269, 2017-04-09: 72.68569443640364 };
I would like to sort it by date, beginning from January, but I have no idea how to do this.
What do you think, is it possible in JS ?
Thanks in advance,
The order of keys is not guaranteed in an object. you can convert your data structure into a sorted array as shown below and iterate over the array in order for your needs:
var obj = {
"2017-05-28": 76.16108625212159,
"2017-02-12": 70.32183347555772,
"2017-05-21": 74.21070693205216,
"2017-04-23": 78.49819059107358,
"2017-03-05": 73.36286201022146,
"2017-04-02": 79.07588060050237,
"2017-01-29": 79.07021235890568,
"2017-03-26": 74.79360018220122,
"2017-01-22": 71.80166785183269,
"2017-04-09": 72.68569443640364
};
var sortedArray = Object.keys(obj).sort().map(function(key) {
return {
date: key,
value: obj[key]
}
});
console.log(sortedArray);
/**Outputs:
[
{
"date": "2017-01-22",
"value": 71.80166785183269
},
{
"date": "2017-01-29",
"value": 79.07021235890568
},
{
"date": "2017-02-12",
"value": 70.32183347555772
},
{
"date": "2017-03-05",
"value": 73.36286201022146
},
{
"date": "2017-03-26",
"value": 74.79360018220122
},
{
"date": "2017-04-02",
"value": 79.07588060050237
},
{
"date": "2017-04-09",
"value": 72.68569443640364
},
{
"date": "2017-04-23",
"value": 78.49819059107358
},
{
"date": "2017-05-21",
"value": 74.21070693205216
},
{
"date": "2017-05-28",
"value": 76.16108625212159
}
]
**/
var obj = '{ "2017-05-28": "76.16108625212159", "2017-02-12": "70.32183347555772", "2017-05-21": "74.21070693205216", "2017-04-23": "78.49819059107358", "2017-03-05": "73.36286201022146", "2017-04-02": "79.07588060050237", "2017-01-29": "79.07021235890568", "2017-03-26": "74.79360018220122", "2017-01-22": "71.80166785183269", "2017-04-09": "72.68569443640364" }';
pobject = JSON.parse(obj);
arr = Object.keys(pobject);
sorted = arr.sort();
len = sorted.length;
for(i=0;i<len;i++)
{
val= pobject[sorted[i]];
console.log(val);
}
This will work
Hope this helps..!
Using Array.prototype.sort() and Array.prototype.reduce()
You can not order object proprieties. so you may need to convert your object to an array
Example
var obj = {
"2017-05-28": 76.16108625212159,
"2017-02-12": 70.32183347555772,
"2017-05-21": 74.21070693205216,
"2017-04-23": 78.49819059107358,
"2017-03-05": 73.36286201022146,
"2017-04-02": 79.07588060050237,
"2017-01-29": 79.07021235890568,
"2017-03-26": 74.79360018220122,
"2017-01-22": 71.80166785183269,
"2017-04-09": 72.68569443640364
},
sortedArr = Object.keys(obj)
.sort(function (a, b) {
return new Date(a) - new Date(b)
})
.reduce(function (acc, item, index) {
acc.push({
date: item,
value: obj[item]
});
return acc;
}, []);
console.log(sortedArr);
Thanks #Shivam for your note
I've got an array of three people. I want to add a new key to multiple objects at once based on an array of indices. Clearly my attempt at using multiple indices doesn't work but I can't seem to find the correct approach.
var array = [
{
"name": "Tom",
},
{
"name": "Dick",
},
{
"name": "Harry",
}
];
array[0,1].title = "Manager";
array[2].title = "Staff";
console.log(array);
Which returns this:
[
{
"name": "Tom",
},
{
"name": "Dick",
"title": "Manager"
},
{
"name": "Harry",
"title": "Staff"
}
]
But I'd like it to return this.
[
{
"name": "Tom",
"title": "Manager"
},
{
"name": "Dick",
"title": "Manager"
},
{
"name": "Harry",
"title": "Staff"
}
]
You cannot use multiple keys by using any separator in arrays.
Wrong: array[x, y]
Correct: array[x] and array[y]
In your case, it will be array[0].title = array[1].title = "manager";
1st method::
array[0].title = "Manager";
array[1].title = "Manager";
array[2].title = "Staff";
array[0,1] will not work.
2nd method::
for(var i=0;i<array.length;i++) {
var msg = "Manager";
if(i===2) {
msg = "Staff"
}
array[i].title = msg
}
You can use a helper function like this
function setMultiple(array, key, indexes, value)
{
for(i in array.length)
{
if(indexes.indexOf(i)>=0){
array[i][key] = value;
}
}
}
And then
setMultiple(array, "title", [0,1], "Manager");
Try this: `
for (var i=0; var<= array.length; i++){
array[i].title = "manager";
}`
Or you can change it around so var is less than or equal to any n range of keys in the index.
EDIT: instead make var <= 1. The point is to make for loops for the range of indices you want to change the title to.
Assuming that you have a bigger set of array objects.
var array = [
{
"name": "Tom",
},
{
"name": "Dick",
},
{
"name": "Harry",
},
.
.
.
];
Create an object for the new keys you want to add like so:
let newKeys = {
'Manager': [0,2],
'Staff': [1]
}
Now you can add more such titles here with the required indexes.
with that, you can do something like:
function addCustomProperty(array, newKeys, newProp) {
for (let key in newKeys) {
array.forEach((el, index) => {
if (key.indexOf(index) > -1) { // if the array corresponding to
el[newProp] = key // the key has the current array object
} // index, then add the key to the
}) // object.
}
return array
}
let someVar = addCustomProperty(array, newKeys, 'title')