I have the object (obj1) that is posted below. As shown in it, it contains an array of objects called "favoritePlayers".
what I am trying to do is, to create a function or add an array prototype so that I can iterate through each element in the array separately and get the following output:
"messi plays in barcelona"
"totti plays in roma"
I tried to solve it as shown below but what I get is
[ 'undefinedplays in[object Object]',
'undefinedplays in[object Object]' ]
obj1:
var obj1 = {
score: [10, 22, 30, 55, 70, 90],
lettersOfMyName: ["a", "m", "r"],
avgScore: null,
favoritePlayers: [
{
name: "messi",
club: "barcelona"
},
{
name: "totti",
club: "roma"
}
],
calcAvgScore: function () {
var sumOfScores = this.score.reduce(function (prev, cur, index, array)
{
return prev + cur;
})
return (sumOfScores / this.score.length);
},
myFavoritePlayersInfo: function () {
console.log(this.favoritePlayers.join());
},
}
my attempts:
//this code was added outside the scope of obj1
Array.prototype.concat1 = ( (array) => {
var tempArray = [];
for (var i = 0; i < array.length; i++) {
tempArray[i] = array.slice(i, i+1).name + "plays in" + array.slice(i,
i+1);
}
return tempArray;
});
update_1
I added the following lines to obj1:
getPlaysIn:function() {
this.favoritePlayers.forEach( (favoritePlayer)=> {
return favoritePlayer.name + " plays in " + favoritePlayer.club;
and I call it as follows:
console.log(obj1.getPlaysIn());
but the results i get is
undefined
You can use Array#map to iterate the players, and create the array you want:
var obj1 = {
score: [10, 22, 30, 55, 70, 90],
lettersOfMyName: ["a", "m", "r"],
avgScore: null,
favoritePlayers: [{
name: "messi",
club: "barcelona"
},
{
name: "totti",
club: "roma"
}
],
getPlaysIn() {
return this.favoritePlayers.map(function(player) {
return player.name + ' plays in ' + player.club;
});
}
};
console.log(obj1.getPlaysIn());
Just iterate the favoritePlayers array
var obj1 = {
score: [10, 22, 30, 55, 70, 90],
lettersOfMyName: ["a", "m", "r"],
avgScore: null,
favoritePlayers: [{
name: "messi",
club: "barcelona"
},
{
name: "totti",
club: "roma"
}
]
}
obj1.favoritePlayers.forEach(function(item) {
console.log(item.name + ' plays ' + item.club)
})
If you want to use prototype
var obj1 = {
score: [10, 22, 30, 55, 70, 90],
lettersOfMyName: ["a", "m", "r"],
avgScore: null,
favoritePlayers: [{
name: "messi",
club: "barcelona"
},
{
name: "totti",
club: "roma"
}
]
}
Array.prototype.customForEach = function() {
for (let i = 0; i < this.length; i++) {
console.log(this[i].name + ' plays ' + this[i].club);
}
}
obj1.favoritePlayers.customForEach();
Iterate through the object and return it the way you see fit.
let playerInfo = obj1.favoritePlayers.map(playerObj => {
return playerObj["name"] + "plays for " + playerObj["club"];
});
Try below code.
var obj1 = {
score: [10, 22, 30, 55, 70, 90],
lettersOfMyName: ["a", "m", "r"],
avgScore: null,
favoritePlayers: [
{
name: "messi",
club: "barcelona"
},
{
name: "totti",
club: "roma"
}
],
getPlaysIn:function() {
var returnVal = "";
this.favoritePlayers.forEach( (favoritePlayer)=> {
returnVal += favoritePlayer.name + " plays in " + favoritePlayer.club+"\n";
});
return returnVal;
}
}
console.log(obj1.getPlaysIn());
var obj1 = {
score: [10, 22, 30, 55, 70, 90],
lettersOfMyName: ["a", "m", "r"],
avgScore: null,
favoritePlayers: [{
name: "messi",
club: "barcelona"
},
{
name: "totti",
club: "roma"
}
]
}
var a = obj1.favoritePlayers;
for(var i = 0; i<a.length; i++){
console.log(a[i].name+ " " + "plays " +" "+ a[i].club)
};
Related
I got an array like this and I need to filter this array with the same user id with all the occurrences with the service_id corresponding to user_id:
Array [
Object {
"service_id": 14,
"user_id": 56,
},
Object {
"service_id": 19,
"user_id": 59,
},
Object {
"service_id": 18,
"user_id": 56,
},
Object {
"service_id": 18,
"user_id": 56,
},
]
And I need to filter the array like this:
Array [
Object {
"user_id": 56,
[
{"service_id":14},
{"service_id": 18}
]
},
Object {
"user_id": 59,
[
{"service_id": 19},
]
},
]
var array = [{"service_id": 14,"user_id": 56,},{"service_id": 19,"user_id": 59,},
{"service_id": 18,"user_id": 56,},{"service_id": 18,"user_id": 56}]
const groupByUserId = (array, key) => {
return array.reduce((result, currentValue) => {(
//Create a new array as key if there is not found
result[currentValue[key]] = result[currentValue[key]] || []).push(currentValue);
return result;
}, {}); // empty object after initialization
};
const grouped = groupByUserId(array, 'user_id');
console.log(grouped)
In Javascript your array should look like this:
var array = [{"service_id": 14,"user_id": 56},{"service_id": 19,"user_id": 59},
{"service_id": 18,"user_id": 56},{"service_id": 18,"user_id": 56}]
There is an assumption to be made here to identify user_id as key in the new grouped array in order to populate the user's similar service_id inside its corresponding array.
const groupByUserId = (array, key) => {
return array.reduce((result, currentValue) => {(
//Create a new array as key if there is not found
result[currentValue[key]] = result[currentValue[key]] || []).push(currentValue);
return result;
}, {}); // empty object after initialization
};
const grouped = groupByUserId(array, 'user_id');
console.log(grouped)
Your output array must be as the below example I suppose.
You can use Array.reduce for that.
const data = [
{
"service_id": 14,
"user_id": 56,
},
{
"service_id": 19,
"user_id": 59,
},
{
"service_id": 18,
"user_id": 56,
},
{
"service_id": 18,
"user_id": 56,
},
]
const output = data.reduce((acc, curr) => {
const node = acc.find((item) => item.user_id === curr.user_id);
if (node) {
node.list.push({service_id: curr.service_id})
} else {
acc.push({
user_id: curr.user_id,
list: [{service_id: curr.service_id}]
})
}
return acc;
}, []);
console.log(output)
I am trying to use below Script to Get the Average of Disconnect Devices .The results are output in group for each Test Customer .
var dataObject = [{
"Customer_Nbr": "13",
"Customer_Name": "Test1",
"Connected_Devices": 7,
"Disconnected_Devices": 1,
"Total_Devices": 8
},
{
"Customer_Nbr": "13",
"Customer_Name": "Test1",
"Connected_Devices": 6,
"Disconnected_Devices": 2,
"Total_Devices": 8
},
{
"Customer_Nbr": "12",
"Customer_Name": "Test3",
"Connected_Devices": 8,
"Disconnected_Devices": 2,
"Total_Devices": 10
}
];
groups = dataObject.reduce(function(r, o) {
var k = o.Customer_Nbr + o.Customer_Name;
if (r[k]) {
if (o.Disconnected_Devices)
(r[k].Disconnected_Devices += o.Disconnected_Devices) && ++r[k].Average;
} else {
r[k] = o;
r[k].Average = 1; // taking 'Average' attribute as an items counter(on the first phase)
}
return r;
}, {});
// getting "average of Points"
var result = Object.keys(groups).map(function(k) {
groups[k].Average = Math.round(groups[k].Disconnected_Devices / groups[k].Average);
return groups[k];
});
console.log(result)
Now I also want grouped output to have a percentage calculation which would be result/Total_Devices * 100 .
Output Should be Something like Assuming Total_Devices Count is constant in Input data -
[
{
Customer_Nbr: '13',
Customer_Name: 'Test1',
Connected_Devices: 7,
Disconnected_Devices: 3,
Total_Devices: 8,
Average: 2
Percent: 25
},
{
Customer_Nbr: '12',
Customer_Name: 'Test3',
Connected_Devices: 8,
Disconnected_Devices: 2,
Total_Devices: 10,
Average: 2
Percent: 20
}
]
Something like this maybe?
var dataObject = [
{
Customer_Nbr: "13",
Customer_Name: "Test1",
Connected_Devices: 7,
Disconnected_Devices: 1,
Total_Devices: 8,
},
{
Customer_Nbr: "13",
Customer_Name: "Test1",
Connected_Devices: 6,
Disconnected_Devices: 2,
Total_Devices: 8,
},
{
Customer_Nbr: "12",
Customer_Name: "Test3",
Connected_Devices: 8,
Disconnected_Devices: 2,
Total_Devices: 10,
},
];
groups = dataObject.reduce(function (r, o) {
var k = o.Customer_Nbr + o.Customer_Name;
if (r[k]) {
if (o.Disconnected_Devices)
(r[k].Disconnected_Devices += o.Disconnected_Devices) && ++r[k].Average;
} else {
r[k] = o;
r[k].Average = 1; // taking 'Average' attribute as an items counter(on the first phase)
}
return r;
}, {});
// getting "average of Points"
var result = Object.keys(groups).map(function (k) {
groups[k].Average = Math.round(
groups[k].Disconnected_Devices / groups[k].Average
);
groups[k].percentage = (groups[k].Average/groups[k].Total_Devices) * 100;
return groups[k];
});
console.log(result);
This previous question comes closest to what I am curious of. I've tried several variations of indexOf() and filter() to no success
I have an arrays of objects (exampleDat):
[{id:1, value:"100", name:"dog", D1: 10, D2: 67, D3: 33},
{id:2, value:"200", name:"cat", D1: 66, D2: 41, D3: 34},
{id:3, value:"300", name:"fish", D1: 23, D2: 45, D3:},
{id:4, value:"400", name:"mouse", D1: 13, D2: 55, D3:},
{id:5, value:"500", name:"snake", D1: 7, D2: 9, D3:}]
In a different function, I return an array of which of these 'keys' I need. This array changes dynamically, so its not possible to type them all out. For example any of the following examples are viable,
useThese1 = ['D1','D2'] //Want exampleDat returned with only these key,value 'columns' returned
useThese2 = ['id','D1','D2','D3'] //Want exampleDat return with only these key,value 'columns' returned
useThese3 = ['value','D2','D3'] //Want exampleDat returned with only these key,value 'columns' returned
So I need to dynamically map the values in a useThese array to the exampleDat array
If I knew the exact columns, I could hand type it ala:
exampleDat.map(d => {return {D1: d.D1, D2: d.D2}})
But I need something like:
dat.map(d => useThese1.map(g => {return {something?}}) ???
In R, it would simply and easily be exampleDat[,colnames(exampleDat) %in% useThese1]
You could map the new keys.
const
mapWith = (array, keys) => array.map(o => Object.fromEntries(keys.map(k => [k, o[k]]))),
data = [{ id: 1, value: "100", name: "dog", D1: 10, D2: 67, D3: 33 }, { id: 2, value: "200", name: "cat", D1: 66, D2: 41, D3: 34 }, { id: 3, value: "300", name: "fish", D1: 23, D2: 45, D3:97}, { id: 4, value: "400", name: "mouse", D1: 13, D2: 55, D3:98}, { id: 5, value: "500", name: "snake", D1: 7, D2: 9, D3:99}],
result1 = mapWith(data, ['D1', 'D2']),
result2 = mapWith(data, ['id', 'D1', 'D2', 'D3']),
result3 = mapWith(data, ['value', 'D2', 'D3']);
console.log(result1);
console.log(result2);
console.log(result3);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Object.fromEntries are relatively recent, but easily polyfilled.
Here is my solution. This uses the ES5 Javascript functions
const selectKeys = (keys, data) => {
return data.map(item => keys.reduce((prev, key) => {
prev[key] = item[key]
return prev
}, {}))
}
const selData1 = selectKeys(useThese1, data)
const selData2 = selectKeys(useThese2, data)
const selData3 = selectKeys(useThese3, data)
You can do something like this
const arr = [
{ id: 1, value: "100", name: "dog", D1: 10, D2: 67, D3: 33 },
{ id: 2, value: "200", name: "cat", D1: 66, D2: 41, D3: 34 },
{ id: 3, value: "300", name: "fish", D1: 23, D2: 45, D3: 34 },
{ id: 4, value: "400", name: "mouse", D1: 13, D2: 55, D3: 34 },
{ id: 5, value: "500", name: "snake", D1: 7, D2: 9, D3: 34 }
];
function dynamicFilter(data, requiredKeys) {
return data.map((item) => {
const result = {};
requiredKeys.forEach(key => result[key] = item[key]);
return result;
});
}
console.log(dynamicFilter(arr, ['D1','D2']));
console.log(dynamicFilter(arr, ['id','D1','D2','D3']));
You can do something like this:
const arr = [{id:1, value:"100", name:"dog", D1: 10, D2: 67, D3: 33}, {id:2, value:"200", name:"cat", D1: 66, D2: 41, D3: 34}, {id:3, value:"300", name:"fish", D1: 23, D2: 45, D3:11}, {id:4, value:"400", name:"mouse", D1: 13, D2: 55, D3:11}, {id:5, value:"500", name:"snake", D1: 7, D2: 9, D3:11}];
const useThese1 = ['D1','D2'];
const useThese2 = ['id','D1','D2','D3'];
const useThese3 = ['value','D2','D3'];
const getResult = (keys) => arr.map(v => keys.reduce((a, c) => (a[c] = v[c], a), {}));
[useThese1, useThese2, useThese3].forEach(v => console.log(getResult(v)));
Here's an imperative way to do it. It could be shortened with ES6 array methods.
let exampleDat = [
{id:1, value:"100", name:"dog", D1: 10, D2: 67, D3: 33},
{id:2, value:"200", name:"cat", D1: 66, D2: 41, D3: 34},
{id:3, value:"300", name:"fish", D1: 23, D2: 45, D3: 8},
{id:4, value:"400", name:"mouse", D1: 13, D2: 55, D3: 8},
{id:5, value:"500", name:"snake", D1: 7, D2: 9, D3: 8}
],
useThese1 = ['D1','D2']
function getColumns(data, useWhich){
let result = [];
for(let row of data){
let keys = Object.keys(row);
let filteredRow = {};
for(let key of keys){
if(useWhich.includes(key)){
filteredRow[key] = row[key];
}
}
result.push(filteredRow);
}
return result;
}
console.log(getColumns(exampleDat, useThese1));
Here's a "for dummies" version of the accepted answer.
(The more verbose variable names helped me understand how the algorithm works.)
const
selectColumns = (unfilteredData, colsToKeep) =>
unfilteredData.map(row =>
Object.fromEntries(colsToKeep.map( col => [col, row[col]] )
)
),
data = [
{ id: 1, value: "100", name: "dog", D1: 10, D2: 67, D3: 33 },
{ id: 2, value: "200", name: "cat", D1: 66, D2: 41, D3: 34 },
{ id: 3, value: "300", name: "fish", D1: 23, D2: 45, D3:97 },
{ id: 4, value: "400", name: "mouse", D1: 13, D2: 55, D3:98 },
{ id: 5, value: "500", name: "snake", D1: 7, D2: 9, D3:99 }
],
colNames1 = ['D1', 'D2'],
result1 = selectColumns(data, colNames1);
console.log(result1);
I wanted to make an exception. It's hard for me to explain it, so let me show you what I mean.
My code:
fruits = [
{name: "apple", energy: 100, not: "kiwi"},
{name: "kiwi", energy: 126, not: "orange"},
{name: "banana", energy: 150, not: ""},
{name: "orange", energy: 118, not: "peach"},
{name: "pineapple", energy: 98, not: ""},
{name: "coconut", energy: 83, not: ""},
{name: "peach", energy: 65, not: ""},
{name: "lemon", energy: 36, not: ""}
]
const pick = (arr, n) => {
const r = [];
for (var i = 0; i < arr.length; i += n) {
const slice = arr.slice(i, i+n);
const name = slice.map(({name}) => name).join('-')
const energy = slice.reduce((r, {energy}) => r + energy, 0);
r.push({name, energy})
}
return r;
}
const result = pick(fruits, 2)
console.log(result)
The result I get is
{name: "apple-kiwi", energy: 226},
{name: "banana-orange", energy: 268},
{name: "pineapple-coconut", energy: 181},
{name: "peach-lemon", energy: 101}
What I want is to make an exception (not in fruits). So apple shouldn't link with kiwi, kiwi with orange, etc. and it should look like this
{name: "apple-banana", energy: something},
{name: "kiwi-pineapple", energy: something},
...
I thought I could filter slice and check if any of it's items contains not, but I failed :(
Could anyone help me?
You need to take an array of names and an array of exceptions, and check them at the intersection:
fruits = [
{name: "apple", energy: 100, not: "kiwi"},
{name: "kiwi", energy: 126, not: "orange"},
{name: "banana", energy: 150, not: ""},
{name: "orange", energy: 118, not: "peach"},
{name: "pineapple", energy: 98, not: ""},
{name: "coconut", energy: 83, not: ""},
{name: "peach", energy: 65, not: ""},
{name: "lemon", energy: 36, not: ""}
]
function intersect (a1, a2) {
var isIntersect = false
a1.forEach(function (a) {
if (a.length > 0 && a2.indexOf(a) !== -1) isIntersect = true
})
return isIntersect
}
const pick = (arr, n) => {
const r = [];
for (var i = 0; i < arr.length; i += n) {
const slice = arr.slice(i, i+n);
const namesArr = slice.map(({name}) => name)
const notsArr = slice.map(({not}) => not)
if (!intersect(namesArr, notsArr)) {
const name = namesArr.join('-')
const energy = slice.reduce((r, {energy}) => r + energy, 0);
r.push({name, energy})
}
}
return r;
}
const result = pick(fruits, 2)
console.log(result)
Actually what you need is to filter the array to select the elements that doesn't have not property's value equal to the iterated item name:
const pick = (arr, n) => {
const r = [];
for (var i = 0; i < arr.length; i += n) {
var slice = [];
slice.push(arr[i]);
slice = slice.concat(arr.filter(function(x, ind) {
return x.name !== arr[i].name && x.not !== arr[i].name
}));
slice = slice.slice(0, n);
var name = slice.reduce((r, {
name
}) => r + name + "-", "");
name = name.replace(/\-$/, '');
const energy = slice.reduce((r, {
energy
}) => r + energy, 0);
r.push({
name,
energy
});
}
return r;
}
Demo:
var fruits = [{
name: "apple",
energy: 100,
not: "kiwi"
},
{
name: "kiwi",
energy: 126,
not: "orange"
},
{
name: "banana",
energy: 150,
not: ""
},
{
name: "orange",
energy: 118,
not: "peach"
},
{
name: "pineapple",
energy: 98,
not: ""
},
{
name: "coconut",
energy: 83,
not: ""
},
{
name: "peach",
energy: 65,
not: ""
},
{
name: "lemon",
energy: 36,
not: ""
}
]
const pick = (arr, n) => {
const r = [];
for (var i = 0; i < arr.length; i += n) {
var slice = [];
slice.push(arr[i]);
slice = slice.concat(arr.filter(function(x, ind) {
return x.name !== arr[i].name && x.not !== arr[i].name
}));
slice = slice.slice(0, n);
var name = slice.reduce((r, {
name
}) => r + name + "-", "");
name = name.replace(/\-$/, '');
const energy = slice.reduce((r, {
energy
}) => r + energy, 0);
r.push({
name,
energy
});
}
return r;
}
const result = pick(fruits, 2)
console.log(result)
I want to change this
var data = [60, rose, 40, rose1, 20, rose2];
to this
var data: [{
value: 60,
name: 'rose'
}, {
value: 40,
name: 'rose1'
}, {
value: 20,
name: 'rose2'
}];
You can do it this way:
var data = [60, "rose", 40, "rose1", 20, "rose2"]
var dataObj = []
for (var i = 0; i < data.length; i+=2) {
dataObj.push({
value: data[i],
name: data[i + 1]
})
}
// Demo Output
document.write(JSON.stringify(dataObj))
Just for the completeness, works even for uneven items:
var data = [60, "rose", 40, "rose1", 20, "rose2", 30],
object = data.reduce(function (r, a, i, d) {
if (i % 2) {
r[d[i - 1]] = a;
}
return r;
}, {});
document.write('<pre>' + JSON.stringify(object, 0, 4) + '</pre>');