I have a var that contains 4 objects that I see when I log it out in the console. But I have been trying to create the structure of this return variable (I want to sort it but first want to recreate the structure), but are failing at the last hurdle.
This is what the console puts out on original variable: [Object, Object, Object, Object]
This is what I get with created variable: [Object]
Here is my code to try and re-create it:
this.obj = [{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'blue'}],
[{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'green'}],
[{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'red'}],
[{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'yellow'}]
;
The first objects of both original and created are identical, but why does it not see my other three objects? If I add two [] around my code, it's sees all four, but then they have changed to arrays instead of objects...
Your code seems broken, if you order it in a readable way then it's clear:
var obj = [
{
items: [{
code: 'bravo', color: 'blue', date: '2017-01-01', pos: 'up'
}, {
code: 'alpha', color: 'blue', date: '2017-01-02', pos: 'down'
}],
color: 'blue'
}] // <=== the array ends here, but now you have this:
, [{ items: [{ ...
The compiler then does this:
var obj = [
{
items: [{
code: 'bravo', color: 'blue', date: '2017-01-01', pos: 'up'
}, {
code: 'alpha', color: 'blue', date: '2017-01-02', pos: 'down'
}],
color: 'blue'
}
], _a = (void 0)[0], _b = ....
As you can see it creates another variable (_a) to store the other data.
Got it working for anyone who wants to know:
this.obj = [{0:{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'blue'}},
{1:{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'green'}},
{2:{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'red'}},
{3:{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'yellow'}}]
;
}
Related
Here is the code (it fails to compile at the sentence that builds the state2, i.e. at the second spread):
let line_id = 6;
let state = {
invoice: {
id: 1015,
description: 'web order',
},
lines: [
{id: 5, description: 'phone', color: 'black'},
{id: 6, description: 'tablet', color: 'blue'},
{id: 7, description: 'computer', color: 'gray'},
]
};
//this alert and this access pattern works, so, I would like to use
//.find... to access element in spread... structure as well
//alert(state['lines'].find(line=>line['id']==line_id)['description']);
let state2 = {
...state,
['lines']: { ...state['lines'],
find(line=>line['id']==line_id): { ...state['lines'].find(line=>line['id']==line_id),
['description']: 'TV',
},
},
};
alert(state2['lines'].find(line=>line['id']==line_id)['description']);
I have state structure, I access lines array, I access the specific line by name-value pair id=6 and I would like to change the value of the field description. This effort is the continuation of https://stackoverflow.com/a/64116308/1375882 in which I am trying to create the general procedure, that use the spread... syntax and the access-by-name strategy for updating the complex object/array tree. In fact - this complex tree is the state of the Redux reducer and that update happend in the action that process the valueSetter function of the AgGrid. But - this is generally the interesting exercise by itself to better understand spread... and JavaScript and JSON structure in JavaScript.
So - the only question is: how to write line
find(line=>line['id']==line_id): { ...state['lines'].find(line=>line['id']==line_id),
so that the code compiles? How can I access the certain element of the array by name-value pair in this setting:
Note, that I am trying to build general code:
find(line=>line[keyFieldName]==keyFieldValue): { ...state['lines'].find(line=>line[keyFieldName]==keyFieldValue),
that uses arbitrary field names and field values - so that such handler can update the any field of the any record of arbitrary 2D AgGrid in React/Redux setting.
The desired result of my code: 1) it should compile; 2) the second alert should return 'TV'.
If I understood correctly what you want to achieve, this should work:
let line_id = 6;
let state = {
invoice: {
id: 1015,
description: 'web order',
},
lines: [{
id: 5,
description: 'phone',
color: 'black'
},
{
id: 6,
description: 'tablet',
color: 'blue'
},
{
id: 7,
description: 'computer',
color: 'gray'
},
]
};
const stateKeyId = 'lines';
const itemKeyId = 'id';
const itemAttr = 'description'
let state2 = {
...state,
[stateKeyId]: state[stateKeyId].map(item => {
if (item[itemKeyId] == line_id) {
return ({
...item,
[itemAttr]: 'TV'
});
}
return item
})
}
console.log(state2);
find(line=>line['id']==line_id) should become [find(line=>line['id']==line_id)], since just like the string it must be between square brackets for js to work properly.
Also, if you are using find from lodash, it will return the object, therefore if you need to use the id as key you can do something like:
[get(find(line => line['id'] === line_id]), 'id')]: whatever
a few observations though:
always please always use === over == in js
avoid snake_case, use camelCase with js, since it's standard
your code is not actually handling missing items correclty, if you need to do so split it in multiple lines since it would be more comprehensible
You can use the map method from arrays to return different elements based on the original one.
Here's how you could use it:
line_id = 6;
state = {
invoice: {
id: 1015,
description: 'web order',
},
lines: [
{id: 5, description: 'phone', color: 'black'},
{id: 6, description: 'tablet', color: 'blue'},
{id: 7, description: 'computer', color: 'gray'},
]
};
state2 = {
...state,
lines: state.lines.map(line => {
if (line.id === line_id)
return { ...line, description: 'YT' }
return { ...line }
})
};
alert(state2['lines'].find(line=>line['id']==line_id)['description']);
I have a function which get a json as parameter, build another json with some values from given json and return builded json.
function getMyJSON(json) {
var result = {
lastUpdate: "",
legends: null
};
result.legends = (new Array(json.legends.length)).fill({
name: null,
rgb: null,
values: null
});
for (let j = 0; j < json.legends.length; j++) {
result.legends[j].name = json.legends[j].name;
result.legends[j].rgb = json.legends[j].rgb;
result.legends[j].values = (new Array(10)).fill(0);
console.log(result.legends[0].name); //PRINT ONLY FIRST ELEMENT
}
console.log(result.legends);
return result;
}
The problem appear after for loop is done. All result.legends have the same value from the last json.legends
Here is how output look:
The legends.name of first element(result.legends[0].name) is changed after every loop.
At the end, all legends.name from result are equal with the last legends.name from json. Why?
I found on google that it is something about variable scope, but I can't figure it out how to do this.
You need independent objects inside of the array. Array#fill takes the same object reference and this leads to the same result in each object.
Instead of this, you could create a new array with Array.from and map new objects with the second parameter for a callback.
result.legends = Array.from(
{ length: json.legends.length },
_ => ({ name: null, rgb: null, values: null })
);
#NinaScholz has described the problem and solved it, however as I mentioned in the comments on the question you can improve and simplify the logic by using map():
var obj = {
legends: [{
name: 'foo',
rgb: 'C00'
},{
name: 'bar',
rgb: 'FFF'
},{
name: 'fizz',
rgb: 'CCFFCC'
},{
name: 'buzz',
rgb: '000000'
}]
}
console.log(getMyJSON(obj));
function getMyJSON(o) {
return {
lastUpdate: "",
legends: o.legends.map(function(item) {
return {
name: item.name,
rgb: item.rgb,
values: (new Array(10)).fill(0)
}
})
};
}
I've been stuck on this for hours.
I have a list of objects:
const myCompanyList = [
{name: 'coca-cola', size: 'big', color: 'red'},
{name: 'my-cola', size: 'small', color: 'purple'},
{name: 'pepsi', size: 'big', color: 'blue'}
];
I need to get it into this format:
myJson = {
companies: {
big: {
coca-cola: {color: 'red'},
pepsi: {color: 'blue'}
},
small: {
my-cola: {color: 'purple'}
}
}
}
I've tried doing this:
wrapperObject = {};
innerObject = {};
for each object in myCompanyList {
innerObject[object.size] = { object.name : {color: object.color}}
}
but the object[name] bit overwrites. How can I write this so I can dynamically get names on each object/map level? Do I need to make another inner object/map to dynamically write the names?
I've tried writing this in Java but I ended up with 5 dimensional maps and it didn't work, so I just wondered if there was something simple I'm missing - answers in Java, javascript or pseudocode thanks.
You can use Array.reduce() to create a map, Try the following :
let myCompanyList = [{name: "coca-cola", size: "big", color: "red"}, {name: "my-cola", size: "small", color: "purple"},{name: "pepsi", size: "big", color:"blue"}];
let result = {};
result.companies = myCompanyList.reduce((a,curr)=>{
a[curr.size] = a[curr.size] || {};
a[curr.size][curr.name] = {"color" : curr.color};
return a;
},{});
console.log(result);
I have the following js code https://repl.it/N0xy/0
I am trying to push some objects into an existing one using some functions:
mylist.push(createMyObject(item.name, item.school, item.teacher))
the result contains :
{ result: true, count: 1, items: [ [ [Object], [Object] ] ] }
instead of :
{ result: true, count: 1, items: [ { name: 'Jacky', school: 'high', teacher: 'good' },
{ name: 'Tom', school: 'college', teacher: 'bad' } ] }
how can i fix this?
thanks
You forgot to do JSON.stringify(obj) in the last statement. Everything else seems fine.
You might want to change the second last line to:
obj.items = create(); as well.
or maybe obj.items = obj.items.concat(create());
You pushed an array to obj.items in stead of the separate items. create() returns an array.
Try this:
create().forEach(function(item) {
obj.items.push(item);
});
OR
let createdItems = create();
for(item of createdItems) {
obj.items.push(item);
}
In your console.log at the end, wrap the obj in a call to JSON.stringify like this:
console.log("print my obj: ",obj);
I must do this: to work over string that i will ask to some user:
text = "";
arr = ["*****"];
arr2 = [];
text = arr.toString();
for(i=0; i<text.length; i++) {
arr2.push(text[i]);
}
---> arr2 = [*,*,*,*,*] <--- thats what i want!.
But i must work with a lot of data like this, so i created and array to content that structured data:
var gems = [
{
name: 'Level-1',
row: {
r1: '*****',
r2: '-***-',
r3: '--*--'
},
canPushtoDb: true,
hideLevel: false,
status: 1
//canvas
},
{
name: 'Level-2',
row: {
r1: '**-**',
r2: '-*-*-',
r3: '-***-',
},
canPushtoDb: true,
hideLevel: false,
status: 1
//canvas
},
{
name: 'Level-3',
row: {
r1: '*-*-*',
r2: '**-**',
r3: '*-*-*'
},
canPushtoDb: true,
hideLevel: true,
status: 1
//canvas
}
];
I want to loop within gems to convert that string on some kind of array, just like I wrote on the beginning of this question.
I was looking on an Angular example, which wrap those objects with a controller.
But for now I'm far to get my code on some refactored version of his own. I just need some hard-coded function or method likegems.name[0].row.r1(this is not working to me!) to get out the object all that I'm working on.
You can iterator over gems as such:
for(var i = 0; i < gems.length; i++) {
...
}
You can then loop through the object as such (within your for loop above)
$.each(var obj in row) {
...Do something with each object found in row
}
To access hardcoded object, your issue was gems.name[0].row.r1
When it should just be gems[0].row.r1
As pointed out by #Patrick Evans, your code is correct except for the fact that arr2 should be arr2 = gems[0].row.r1. Have a look at this JSFiddle.