I'm just wondering if it's possible to refer to self (object) value inside the object sibling like below?
[
{
"name": "Zulh",
"name_uppercase": uppercase(self.name) // expects ZULH
},
{
"name": "John",
"name_uppercase": uppercase(self.name) // expects JOHN
}
]
Note:
Code for uppercase is omitted for brevity. In my real code, it's doing synchronous complex stuff and is not actually simple string case manipulation like that.
Using a GETTER
If you want to keep it dynamic and make it work even if you change the name property, you can use a GETTER to do this kind of thing:
const names = [
{
"name": "John",
get name_uppercase() {
return this.name.toUpperCase();
}
}
]
console.log(names[0].name_uppercase)
GETTER for multiple objects
You don't have to write this for every property manually! Use .forEach:
const names = [
{
"name": "John"
},
{
"name": "Mike"
}
]
names.forEach(object => {
Object.defineProperty(object, 'nameUppercase', {
get: function() { return this.name.toUpperCase() }
});
});
console.log(names[0].nameUppercase)
console.log(names[1].nameUppercase)
Using a class and a GETTER
Or as #Rajesh pointed out you can use a class instead:
class Person {
constructor(name) {
this.name = name;
}
get nameUpperCase() {
return this.name.toUpperCase();
}
}
const names = [ new Person("John"), new Person("Mike")];
console.log(names[0].nameUpperCase);
console.log(names[1].nameUpperCase);
You can't reference an object during initialization when using object literal syntax.. Inshort, that's not possible what you expect above
Well, you can use map and add additional/modified properties to you object like
data.map(o=> ({name: o.name, upper_case : o.name.toUpperCase()}))
var data = [
{
"name": "Zulh"
},
{
"name": "John"
}
];
var x = data.map(o=> ({name: o.name, upper_case : o.name.toUpperCase()}))
console.log(x)
You can use Array.forEach and update the objects in Array
var data = [{"name": "Zulh"},{"name": "John"}];
data.forEach(o=> o.upper_case = o.name.toUpperCase());
console.log(data);
Why not create a function that transforms your incoming array? A way to do it could be like this:
const value = [
{
"name": "Zulh"
},
{
"name": "John"
}
];
const transform = ( array, propertyToUpdate, propertyToCreate, transformation ) => {
return array.map( item => ({ ...item, [propertyToCreate]: transformation( item[propertyToUpdate] ) }) );
};
console.log( transform( value, 'name', 'name_uppercase', ( item ) => item.toUpperCase() ) );
You can't do this with the object literal syntax, since it's 'this' property will not be set at that time. For example, if you'd run your code in the browser, 'this' would refer to the window object.
So you'll either have to use one of the other answers or go for a 'class':
var uppercase = function( str ) {
return str.toUpperCase();
};
var Person = function( name ) {
this.name = name;
this.name_uppercase = uppercase( this.name );
};
var persons = [
new Person( 'zuhi' ),
new Person( 'john' )
];
console.log( persons );
Same can be written in ES6 class syntax.
I would suggest 2 approaches:
If you DO NOT want to change your initial array ( which is recommended ), use map which returns a new array with changed values ( calls a function for every array item ) .
See below
let arr = [
{
"name": "Zulh",
},
{
"name": "John",
}
];
const newArr = arr.map((x)=>{
x.name_uppercase = (x.name).toUpperCase()
return x
})
console.log(newArr)
If you don't mind changing your initial array, you can use forEach. Keep in mind that unlike map, forEach changes your array and so it doesn't return anything.
let arr = [
{
"name": "Zulh",
},
{
"name": "John",
}
];
arr.forEach((x)=>{
x.name_uppercase = (x.name).toUpperCase()
})
console.log(arr)
So it all depends if you want to change your current array or not
How about using a getter method?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
The get syntax binds an object property to a function that will be
called when that property is looked up.
foo = [
{
"name": "Zulh",
get name_uppercase () {
return (this.name).toUpperCase();
}
},
{
"name": "John",
get name_uppercase () {
return (this.name).toUpperCase();
}
}
]
console.log(foo[1].name_uppercase); //returns JOHN
Hope it helps :)
Related
I have a list of objects like this
var obj = [
{ name: "user", per: { pu: [{ end: "foo" }], ge: [{ end: "bar" }] } },
{ name: "user2", per: { pu: [{ end: "foo2" }], ge: [{ end: "bar2" }] } }
];
I want to add a new property cond which is a function to the objects in pu and ge, but when i do this, the function set to the only last object.
I loop through them then set them like so obj[0].per[itm][0].cond = func and that set to the last object only, but when i try to convert function toString() it set to all, JSON.stringfy() works as func same behavior.
Have I clone or set it in another way?
You may need to post fuller code as it's difficult to see where your error is. However, considering it from scratch, I think some nested loops to match the nested arrays will get you there.
for (let o of obj) {
for (let puObj of o.per.pu) {
puObj.cond = func;
}
for (let geObj of o.per.ge) {
geObj.cond = func;
}
}
use the below function...
const updateObject = (oldObject, updatedProperties) => {
return {
...oldObject,
...updatedProperties
}
};
then you can pass in your new function or anything you need to add like this:
obj[index].per = updateObject(obj[index].per, {cond : function() {}} ); //use a loop to add the function to all objects in array
//check your current obj
console.log(obj);
I cannot get an if statement to work inside a function called by a forEach array loop.
I have an array with objects, (with an object)
arrofobj = [
{"thing_id":"1a", "val": 1, "Type": "Switch","ValType":{"0":"Open","1":"Closed"}},
{"thing_id":"1b", "val": 72, "Type": "Sensor","ValType":{"0":"%"}}]
I would like to test if the Type is a switch, in order to write info in a new field of the objects of the array CatX:
- when it is, I want to use the val value to determine which ValType element to use in a new variable of array arrofobj.
- if not, I want to use the arrofobj.ValType.0 value
const getCat = function(){
if(arrofobj.Type !== 'Switch')
arrofobj.ValType'.0'
} else {
arrofobj.ValType.(arrofobj.val)
};
arrofobj.forEach(p => p.CatX = getCat() );
I am not getting the lint to accept the code, so cannot test.
1) You have to use bracket notation to access properties as strings.
2) You have to close the brackets on if/else correctly.
3) You have to return something from inside getCat to have something to assign to p.CatX
4) You have to actually send the object to getCat inside the loop.
const arrofobj = [
{"thing_id":"1a", "val": 1, "Type": "Switch","ValType":{"0":"Open","1":"Closed"}},
{"thing_id":"1b", "val": 72, "Type": "Sensor","ValType":{"0":"%"}}
];
const getCat = function( obj ){
if(obj.Type !== 'Switch') {
return obj.ValType[ '0' ]
} else {
return obj.ValType[ obj.val ];
}
};
arrofobj.forEach(p => {
p.CatX = getCat(p);
});
console.log( arrofobj );
Just to add to Shilly's answer:
1) In the long-run, if this is data you're creating yourself and not something from a 3rd-party endpoint, you'll find standardising the format of your object property key names (in camelCase) to be easier to work with. It won't introduce as many bugs to your code if they're identically formatted.
2) You can use object destructuring assignment and a ternary operator to shorten the code footprint a little.
const arrofobj = [
{ id: '1a', val: 1, type: 'Switch', valType: { '0': 'Open', '1': 'Closed' } },
{ id: '1b', val: 72, type: 'Sensor', valType: { '0': '%' } }
];
function getCat(obj) {
// Deconstruct the properties from obj
const { type, valType, val } = obj;
// Use a ternary operator to decide what to return
return type === 'Switch' ? valType[val] : valType['0'];
}
arrofobj.forEach(obj => {
obj.catX = getCat(obj);
});
console.log(arrofobj);
How to add attribute to the root of JSON object consists of array of objects?
If my JSON object something like that:
[
{
"Id":"f2ac41c5-b214-48f6-ad40-9fc35c1aaad9",
"Name":"W",
"NumberOfWorkHours":8,
"NumberOfShortDays":1,
"WorkTimeRegulationId":"f5833075-2847-4cc3-834d-6138dd0dcd99"
},
{
"Id":"5c267601-fcf2-4735-9e49-b4def3981648",
"Name":"S",
"NumberOfWorkHours":6,
"NumberOfShortDays":0,
"WorkTimeRegulationId":"8d14580e-278f-41d1-9239-8874be792580"
}
]
I do the following:
worktimeJSON.Id = $('.Js-WorkTime-id').val();
worktimeJSON.Name = $('.Js-WorkTime-name').val();
worktimeJSON.NumberOfAvailableRotations = $('.Js-WorkTime-rotations').val();
And make sure that the jQuery fetching data from the inputs but this doesn't work.
This will change property of all object in array if you want to change in particular then use index for this for exp->
worktimeJSON[0].Id = $('.Js-WorkTime-id').val();
worktimeJSON[0].Name = $('.Js-WorkTime-name').val();
worktimeJSON[0].NumberOfAvailableRotations = $('.Js-WorkTime-rotations').val();
var worktimeJSON = [
{
"Id":"f2ac41c5-b214-48f6-ad40-9fc35c1aaad9",
"Name":"W",
"NumberOfWorkHours":8,
"NumberOfShortDays":1,
"WorkTimeRegulationId":"f5833075-2847-4cc3-834d-6138dd0dcd99"
},
{
"Id":"5c267601-fcf2-4735-9e49-b4def3981648",
"Name":"S",
"NumberOfWorkHours":6,
"NumberOfShortDays":0,
"WorkTimeRegulationId":"8d14580e-278f-41d1-9239-8874be792580"
}
];
worktimeJSON = worktimeJSON.map(function(val){
val.Id = $('.Js-WorkTime-id').val();
val.Name = $('.Js-WorkTime-name').val();
val.NumberOfAvailableRotations = $('.Js-WorkTime-rotations').val();
return val;
});
Push can do the job.
let worktimeJSON = [
{
"Id":"f2ac41c5-b214-48f6-ad40-9fc35c1aaad9",
"Name":"W",
"NumberOfWorkHours":8,
"NumberOfShortDays":1,
"WorkTimeRegulationId":"f5833075-2847-4cc3-834d-6138dd0dcd99"
},
{
"Id":"5c267601-fcf2-4735-9e49-b4def3981648",
"Name":"S",
"NumberOfWorkHours":6,
"NumberOfShortDays":0,
"WorkTimeRegulationId":"8d14580e-278f-41d1-9239-8874be792580"
}
];
worktimeJSON.push
({
id: "someID",
name: "toto",
WorkTimeRegulationId: 42
});
console.log(worktimeJSON);
I structure my object like this:
let WorkTimeRegulationViewModelJSON = {
Id: $('.Js-WorkTimeRegulation-id').val(),
Name: $('.Js-WorkTimeRegulation-name').val(),
NumberOfAvailableRotations: $('.Js-WorkTimeRegulation-rotations').val(),
AssignedWorkTimes: JSON.parse(worktimeJSON)
};
I am trying to dynamically create an n dim object finalObj looking like this for n=3
children = { 'value1' : 'some1' , 'value2' : 'some2' , 'value3' :'some3' }
item = { 'key1' : 'value1' , 'key2':'value2' , 'key3':'value3' }
basically, the resulting object would look like this.
finalObj = { parent : { 'some1' : { 'some2' : { 'some3':{} } } } }
I am creating an n-depth Object below here.
var parent ={}
var finalObj
function makechildren( children, depth ){
if (depth>0){
makechildren({children}, depth-1);
}
else
{ finalObj=children
console.log('finalObj',finalObj)
}
return finalObj
}
Promise.resolve(makechildren(parent,4))
.then(function(resp){
console.log("resp is",resp);
})
This prints:
{ "children": { "children": { "children": { "children": {} } } } }
Now, how to turn
parent.children.children.children
with
item ={'key1':'value1','key2':'value2','key3':'value3'}
into
parent.children[ item['key1']].children[ item['key2']].children[ item['key3']]
which is essentially
parent.children['value1'].children['value2'].children['value3']....
I have tried making a copy of the original dictionary and altering the keys with a loop and assigning each parent.children[ item['key1']] to the rest of the multidimensional dictionary but didnt go really far.
parent1 = JSON.parse(JSON.stringify(parent))
for (i in Object.keys(parent))
{
parent1[ item['key'+i] ] = parent.children
}
However, iam stuck here on how to complete it this way. Any idea?
Loop through the values in item, using each one to get the corresponding value from children, and use this as the property for a new object. To make the nested object, use a variable to hold the object at the current depth, which you update each time through the loop.
children = { 'value1' : 'some1' , 'value2' : 'some2' , 'value3' :'some3' };
item = { 'key1' : 'value1' , 'key2':'value2' , 'key3':'value3' };
finalObj = { parent: {} };
var cur = finalObj.parent;
Object.values(item).forEach(val => {
cur[children[val]] = {};
cur = cur[children[val]];
});
console.log(JSON.stringify(finalObj));
Note that the order of items read from an object is not guaranteed, so there's no assurance that this will nest things in the desired order. You should use an array if you want order to be maintained.
https://jsfiddle.net/adamchenwei/Lyg2jy61/7/
RESOLVED VERSION:
https://jsfiddle.net/adamchenwei/Lyg2jy61/10/
For some reason findKey for parent top level got undefined
My objective is to get the result = 'myName' with lodash;
var obj = {
myName: {
Adam: 'Man',
},
herName: {
Eve: 'Woman',
},
};
var result = _.findKey(obj, '0'); //as you can see somehow its undefined!
var result2 = _.findKey(obj.myName, '0');
console.log(result);//objective is to get the result = 'myName' with lodash;
console.log(result2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script>
It looks like what you're actually trying to do is get the first key of an object. To get the keys of an object, you can use _.keys. Then just retrieve the first one.
var obj = {
myName: {
Adam: 'Man',
},
herName: {
Eve: 'Woman',
},
};
console.log(_.keys(obj)[0]);
// Or if you want to do it exclusively with lodash functions
console.log(_.first(_.keys(obj)));
// or
console.log(_.head(_.keys(obj)));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script>
It's not clear what you're after exactly, but using _.findKey on the object you have posted would work like this:
https://jsfiddle.net/Lyg2jy61/8/
var obj = {
myName: {
Adam: 'Man',
},
herName: {
Eve: 'Woman',
}
};
console.log(_.findKey(obj, function(o) { return !!o.Adam; }));
If you just want the first key: _.keys(obj)[0]