I have the following code where I'm attempting to reference the values of one JSON object with the variables of another:
const ch = {
"columns": {
"COL1": {
"position": 1,
"composites": ["VAR1", "VAR3"]
},
"COL2": {
"position": 3,
"composites": ["VAR2"]
},
"COL3": {
"position": 2,
"composites": ["VAR4"]
}
}
}
const dataset = [{
"VAR1": "alpha",
"VAR2": 2,
"VAR3": "1015",
"VAR4": "z",
},
{
"VAR1": "beta",
"VAR2": 701,
"VAR3": "1023",
"VAR4": "z"
}
]
for (let l = 0; l < dataset.length; l++) {
for (const {
position,
composites
} of Object.values(ch.columns).sort((a, b) => a.position - b.position)) {
console.log(position, composites[0], dataset[l].VAR1)
/* eval[dataset[l].composites[0]], this[dataset[l].composites[0]]*/
}
}
The program correctly orders the columns and I can refer both values from 'ch', but I would like to use the first composites value as a variable reference to the dataset. Having googled the question I followed a couple of recommendations to either use 'this' or 'eval', but neither work. Where am I going wrong?
Ideally, if I could get the commented out code working the log should look like the following:
1 VAR1 alpha alpha
2 VAR4 alpha z
3 VAR2 alpha 2
1 VAR1 beta beta
2 VAR4 beta z
3 VAR2 beta 701
Use dataset[l][composites[0]] to get the additional column. See Dynamically access object property using variable
const ch = {
"columns": {
"COL1": {
"position": 1,
"composites": ["VAR1", "VAR3"]
},
"COL2": {
"position": 3,
"composites": ["VAR2"]
},
"COL3": {
"position": 2,
"composites": ["VAR4"]
}
}
}
const dataset = [{
"VAR1": "alpha",
"VAR2": 2,
"VAR3": "1015",
"VAR4": "z",
},
{
"VAR1": "beta",
"VAR2": 701,
"VAR3": "1023",
"VAR4": "z"
}
]
for (let l = 0; l < dataset.length; l++) {
for (const {
position,
composites
} of Object.values(ch.columns).sort((a, b) => a.position - b.position)) {
console.log(position, composites[0], dataset[l].VAR1, dataset[l][composites[0]])
}
}
Related
I have an object like this in my NodeJS backend:
{
"x": "2021",
"y": {
"Kumada, K": 2,
"Wu, XY": 4,
"da Silva, BJP": 2
}
}
And i would need it to become like this:
{
"x": "2021",
"Kumada, K": 2
"Wu, XY": 4,
"da Silva, BJP": 2
}
EDIT: The "y" is dynamic which means it can have any number of different names, for example:
{
"x": "2021",
"y": {
"Josh, K": 2,
"Bob": 4,
"Joseph": 2,
"John": 0
}
}
Any tips? Appreciate any help!
Below approach first creates an object based on a.y and then add all properties from a one by one using Object.keys(). Then it removes the y key, since it is not required.
let a = {
"w" : "Hello",
"x": "2021",
"y": {
"Kumada, K": 2,
"Wu, XY": 4,
"da Silva, BJP": 2
}
}
let b = a.y;
Object.keys(a).forEach((x)=>{
b[x] = a[x];
})
delete b.y
This will be a shallow copy
For eg : If you have a["x"] as { 'prop1' : 22, 'prop2' : 33 }. And you modify a["x"]["prop1"] = 22; This will be reflected in your final object too.
Get to know spread syntax. It's magic sauce for this kind of thing
let o = {
"x": "2021", "y": { "Kumada, K": 2, "Wu, XY": 4, "da Silva, BJP": 2 }
}
let newobj = { ...o, ...o.y };
delete newobj.y;
console.log(newobj)
I can't set up an algo that counts my occurrences while respecting ESlint's 6 standards in javascript.
My input table is :
[
{
"id": 2,
"name": "Health",
"color": "0190fe"
},
{
"id": 3,
"name": "Agriculture",
"color": "0190fe"
},
{
"id": 1,
"name": "Urban planning",
"color": "0190fe"
},
{
"id": 1,
"name": "Urban planning",
"color": "0190fe"
}
]
And i want to get :
{"Urban planning": 2, "Health": 1, ...}
But that does not work with ESLINT / REACT compilation...
This is my code :
const jsonToIterate = *'MyPreviousInputJson'*
const names = []
jsonToIterate.map(item => (names.push(item.name)))
const count = []
names.forEach(item => {
if (count[item]){
count.push({text: item, value: 1})
} else {
count.forEach(function(top){top.text === item ? top.value =+ 1 : null})
}
})
Thank you so much
Well, you want an object in the end, not an array, so count should be {}. I also wouldn't use map if you're not actually returning anything from the call. You can use reduce for this:
let counts = topicsSort.reduce((p, c, i, a) => {
if (!p.hasOwnProperty(c.name)) p[c.name] = 0;
p[c.name]++;
return p;
}, {});
I'm half exppecting someone to close this as a duplicate because all you've asked for is a frequency counter. But here's an answer anyway:
const jsonToIterate = *'MyPreviousInputJson'*;
const names = {};
jsonToIterate.map(obj => {
if(obj.name in names){
names[obj.name]++
}
else{
names[obj.name] = 1;
}
})
I have an array of ~1800 object represents games played in a league. I need a new array that has an object for each team, and will include 4 new fields (wins, losses, ties, and points). Here is a sample of the array I am working with:
[
{
"homeGoals": 2,
"gameId": "12221",
"homeTeam": {
"id": "aasfdsf1",
"teamName": "Team 1"
},
"awayTeam": {
"id": "aasfdsf2",
"teamName": "Team 2"
},
"id": "ggaew1",
"awayGoals": 4
},
{
"homeGoals": 5,
"gameId": "12222",
"homeTeam": {
"id": "aasfdsf1",
"teamName": "Team 1"
},
"awayTeam": {
"id": "aasfdsf3",
"teamName": "Team 3"
},
"id": "ggaew2",
"awayGoals": 1
},
{
"homeGoals": 4,
"gameId": "12223",
"homeTeam": {
"id": "aasfdsf2",
"teamName": "Team 2"
},
"awayTeam": {
"id": "aasfdsf3",
"teamName": "Team 3"
},
"id": "ggaew3",
"awayGoals": 4
},
{
"homeGoals": null,
"gameId": "12223",
"homeTeam": {
"id": "aasfdsf2",
"teamName": "Team 2"
},
"awayTeam": {
"id": "aasfdsf3",
"teamName": "Team 3"
},
"id": "ggaew4",
"awayGoals": null
}
]
And here is an example of what I need the result to look like:
[
{
"id": "aasfdsf1",
"name": "Team 1",
"wins": 1,
"losses": 1,
"ties": 0,
"points": 2
},
{
"id": "aasfdsf2",
"name": "Team 2",
"wins": 1,
"losses": 0,
"ties": 1,
"points": 3
},
{
"id": "aasfdsf3",
"name": "Team 3",
"wins": 0,
"losses": 1,
"ties": 1,
"points": 1
}
]
Some games have not been played, so the homeGoals and awayGoals fields will be null.
So far I have a list of unique teams, only where the games have been completed:
const completedGames = games.filter(x => x.homeGoals !== null)
const homeTeams = [...new Set(completedGames.map(x => x['homeTeam']))];
const awayTeams = [...new Set(completedGames.map(x => x['awayTeam']))];
const teams = [...new Set([...homeTeams, ...awayTeams])]
I know I need to do some sort of reduce function, but am having trouble figuring it. I am pretty sure the step I just did before would be irrelevant if I had a proper map reduce function. Any help would be greatly appreciated !
This can be expressed in a simpler way with flatMap. It's not built-in in JS, but easy to implement:
let flatMap = (a, fn) => [].concat(...a.map(fn));
Now, on the map step, you can emit two "result" object per game (or no results at all if the game is incomplete):
results = flatMap(data, g => {
if (g.homeGoals === null || g.awayGoals === null)
return [];
if (g.homeGoals > g.awayGoals)
return [
{id: g.homeTeam.id, r: 'win'},
{id: g.awayTeam.id, r: 'loss'},
];
if (g.homeGoals < g.awayGoals)
return [
{id: g.homeTeam.id, r: 'loss'},
{id: g.awayTeam.id, r: 'win'},
];
if (g.homeGoals === g.awayGoals)
return [
{id: g.homeTeam.id, r: 'tie'},
{id: g.awayTeam.id, r: 'tie'},
];
});
This creates an array like
{ id: 'aasfdsf1', r: 'loss' },
{ id: 'aasfdsf2', r: 'win' },
{ id: 'aasfdsf1', r: 'win' }, etc
which is easy to reduce:
summary = results.reduce((m, {id, r}) => {
let e = m[id] || {};
e[r] = (e[r] || 0) + 1;
return Object.assign(m, {[id]: e})
}, {});
You can also make is less verbose by encoding wins, losses and ties by 1, -1, 0 respectively, in which case the mapper becomes:
results = flatMap(
data.filter(g => g.homeGoals !== null),
g => {
let d = g.homeGoals - g.awayGoals;
return [
{id: g.homeTeam.id, r: Math.sign(+d)},
{id: g.awayTeam.id, r: Math.sign(-d)},
]
});
I think you are looking to something like this:
const hashMapTeams = games.filter(x => x.homeGoals !== null)
.reduce((res, match)=>{
/* do the calculations here */
/* put the values on the res object, using res as a HashMap*/
res["/*the home team id*/"].id = /*id value*/
res["/*the home team id*/"].name = /*name value*/
res["/*the home team id*/"].wins= /* the right value */;
res["/*the home team id*/"].losses= /* the right value */;
res["/*the home team id*/"].ties= /* the right value */;
res["/*the home team id*/"].points= /* the right value */;
res["/*the away team id*/"].id = /*id value*/
res["/*the away team id*/"].name = /*name value*/
res["/*the away team id*/"].wins= /* the right value */;
res["/*the away team id*/"].losses= /* the right value */;
res["/*the away team id*/"].ties= /* the right value */;
res["/*the away team id*/"].points= /* the right value */;
},{});
/* This will convert again the object to an array */
const arrayTeams = Object.keys(hashMapTeams).map(function (key) { return hashMapTeams[key]; });
This gets the exactly result you are looking for:
{
"id": "aasfdsf1",
"name": "Team 1",
"wins": 1,
"losses": 1,
"ties": 0,
"points": 2
},
I used tenary and brackets to show you more than one way to approach that, you can use either one.
let result = [];
your1800ArrayObj.map(data => {
let wins = data.wins ? data.wins : 0;
let losses = data.losses ? data.losses : 0;
let ties = data['ties'] || 0;
let points = data['points'] || 0;
if (data.homeGoals === null && data.awayGoals === null) {
console.log('game not played')
} else {
if (data.homeGoals > data.awayGoals) {
wins += 1
points += 1
} else if (data.homeGoals < data.awayGoals) {
losses += 1
} else {
ties += 1
}
}
result.push({
id: data.id,
name: data.homeTeam.teamName ,
wins: wins,
losses: losses,
ties: ties,
points: points
})
})
return result
}
I have a object like this
{
"items":{
"2":{
"id":122,
"product_id":"DE",
"price":"9.35",
},
"4":{
"id":15,
"product_id":"CH",
"price":"8.00",
}
"7":{
"id":78,
"product_id":"CH",
"price":"3.00",
}
},
"total_price":"20.35",
"item_count":2,
"unit":"CHF"
}
Do you know how i reset the items order.
now 2, 4, 7
should be 0, 1, 2
Created a JSfiddle that shows you a way.
Im using a custom format function:
function format(object) {
var items = {};
var i = 0;
for (var index in object.items) {
items[i] = object.items[index];
i++;
}
object.items = items;
}
The resulted object is this:
{
"items": {
"0": {
"id": 122,
"product_id": "DE",
"price": "9.35"
},
"1": {
"id": 15,
"product_id": "CH",
"price": "8.00"
},
"2": {
"id": 78,
"product_id": "CH",
"price": "3.00"
}
},
"total_price": "20.35",
"item_count": 2,
"unit": "CHF"
}
How about this
var obj = {
"items":{
"2":{
"id":122,
"product_id":"DE",
"price":"9.35",
},
"4":{
"id":15,
"product_id":"CH",
"price":"8.00",
},
"7":{
"id":78,
"product_id":"CH",
"price":"3.00",
}
},
"total_price":"20.35",
"item_count":2,
"unit":"CHF"
}
var keys = Object.keys(obj.items)
for (var i = 0; i < keys.length; i++) {
obj.items[i] = obj.items[keys[i]];
delete obj.items[keys[i]];
};
console.log(obj);
Object properties do not have order. I assume you want to re-name the properties, counting up from 0, but have the properties maintain the original relative ordering of their keys. (So the property with the smallest name is renamed to 0, the second-to-smallest is 1, etc.)
To do this, get all the property names, and sort the names numerically. Then, get all the values in the same over as their sorted property names. Finally, re-insert those property values with their new property names.
var itemsObj = obj["items"];
// get all names
var propertyNames = Object.keys(itemsObj);
// sort property names in numeric order: ["2", "4", "7"]
propertyNames.sort(function(a,b){ return a-b; });
// get property values, sorted by their property names
// ["2", "4", "7"] becomes [{ "id":122, .. }, { "id":15, ... }, { "id":78, ... }]
var values = propertyNames.map(function(propName) { return itemsObj[propName]; }
// clear out old property and add new property
for(var i=0; i<values.length; ++i) {
delete itemsObj[propertyNames[i]];
itemsObj[i] = values[i];
}
var data = {
"items": {
"2": {
"id": 122,
"product_id": "DE",
"price": "9.35",
},
"4": {
"id": 15,
"product_id": "CH",
"price": "8.00",
},
"7": {
"id": 78,
"product_id": "CH",
"price": "3.00",
}
},
"total_price": "20.35",
"item_count": 2,
"unit": "CHF"
};
var indices = Object.keys(data.items).map(function(i) { return parseInt(i, 10); }),
counter = 0;
indices.sort();
indices.forEach(function (i) {
if (i > counter) { // put here some more collision detecting!
data.items[counter] = data.items[i];
delete data.items[i];
counter++;
}
});
Object properties order is not guaranteed anyway. You should use an array instead.
Take a look at this answer
how would I reduce bunch of deeply nested arrays and get the biggest value for certain keys?
here is my data format:
var data = [
{
"category": "Cat 1",
"subcategories": [
{
"subcategory": "Subcate 1 a",
"problems": [
{
"problem": "Problem 1 a 1",
"total": 3,
"breakdown": {
"moderate": 1,
"severe": 2
}
},
{
"problem": "Problem 1 a 2",
"total": 6,
"breakdown": {
"moderate": 5,
"severe": 1
}
}
]
}
]
},
{
"category": "Cat 2",
"subcategories": [
{
"subcategory": "Subcate 2 a",
"problems": [
{
"problem": "Problem 2 a 1",
"total": 8,
"breakdown": {
"moderate": 5,
"severe": 3
}
}
]
},
{
"subcategory": "Subcat 2 b",
"problems": [
{
"problem": "Problem 2 b 1",
"total": 4,
"breakdown": {
"moderate": 1,
"severe": 3
}
},
{
"problem": "Problem 2 b 2",
"total": 2,
"breakdown": {
"moderate": 2,
"severe": 0
}
}
]
}
]
}
]
How would I get an array of every value for "moderate" and "severe"? So in this example I would need
[1,2,5,1,5,3,1,3,2,0]
And then I would like to do d3.max(array) to get the biggest value from it.
This is the working fiddle .Just convert the object into array like this:
var array = $.map(data, function(value, index) {
return [value];
});
var arr =[];
for(var key in array)
{
var subcategories = array[key]['subcategories'];
for(var j in subcategories)
{
var prob = subcategories[j]['problems'];
for(var i in prob)
{
var moderate = prob[i]['breakdown']['moderate'];
var severe = prob[i]['breakdown']['severe'];
arr.push(moderate);
arr.push(severe);
}
}
}
alert(arr); //required array
var max = d3.max(arr) //required max value
and loop through it and save the values into a final array!
This is a little long-winded but it might work:
var array = new Array();
for (var h=0; h<data.length; h++){
for (var i=0; i<data[h].length; i++){
for (var j=0; j<data[h].subcategories[i].length; j++){
for (var k=0; k<data[h].subcategories[i].problems[j].length; k++){
array.push(data[h].subcategories[i].problems[j].breakdown.moderate);
array.push(data[h].subcategories[i].problems[j].breakdown.severe);
}
}
}
}
//Then get the max of array
I may have made a mistake somewhere, but you could use this general idea to produce the desired result.
In order to pass deeply nested json use jsonpath jQuery plugin
Fiddle
JS:
var mod=jsonPath(data, '$..subcategories..problems..moderate');
var path=mod.concat(jsonPath(data, '$..subcategories..problems..severe'));
$("#max").html(d3.max(path));