Reputation: 13
I have a javascript module representing a physical model and its data is provided in a data object. This module exports a setter function to set properties of the data object (Note: export removed in example below)
This works very well on the top hierarchical level but how to set specific values inside properties, e.g. a specific field of an array property?
var modeldata = {
current: 100,
pipeline: [150,200,210,220]
}
set = (variable, val) => {
if (modeldata[variable] == undefined) {
console.log('modeldata['+variable+'] is not defined');
} else {
if (modeldata[variable] == val) {
console.log('no change necessary');
} else {
var old = modeldata[variable];
modeldata[variable] = val;
console.log('changing modeldata['+variable+']: ' + old + ' to ' + modeldata[variable])
}
}
}
set('curren', 100); // modeldata[curren] is not defined, OK
set('current', 100); // no change necessary, OK
set('current', 120); // changing modeldata[current]: 100 to 120, OK
set('pipeline[0]', 42); // modeldata[pipeline[0]] is not defined, FAIL
How to make the set
function issue modeldata['pipeline'][0] = 42;
instead but still allow to set the current
property as it works now?
I could simply create a specific setter for each property but I have > 100 properties and the amount of properties is not fixed.
Also, I could call set('pipeline', ...)
and simply overwrite the whole array including the new data. But as stated above, I want to change only a specific field of the array without knowing or touching everything else.
Update: I'm looking for a solution where modeldata
is only accessed within the set
-function and there is no get
-function available. Thus, set
is my only interface to modeldata
.
Upvotes: 1
Views: 91
Reputation: 386644
Just walk the path.
var modeldata = {
current: 100,
pipeline: [150, 200, 210, 220]
}
function set(variable, val) {
var path = variable.replace(/\[(\d+)\]/g, '.$1').split('.'),
target = path.pop(),
reference = path.reduce(function (r, k) { return r[k]; }, modeldata);
if (target in reference) {
if (reference[target] === val) {
alert(variable + ' = ' + val + '\nno change necessary');
} else {
reference[target] = val;
}
} else {
alert(variable + ' is not defined');
}
}
set('curren', 100); // modeldata[curren] is not defined, OK
set('current', 100); // no change necessary, OK
set('current', 120); // changing modeldata[current]: 100 to 120, OK
set('pipeline[0]', 42); // changing modeldata[pipeline.0]: 150 to 42, OK
document.write('<pre>' + JSON.stringify(modeldata, 0, 4) + '</pre>');
Upvotes: 0
Reputation: 997
This is an edit to the set function in order to allow arrays and sub-properties changes:
set = (variable, val) => variable.split('.').reduce((prev, curr, i, arr) => {
if (i === arr.length - 1) {
if (prev[curr] == undefined) {
console.log('modeldata[' + variable + '] is not defined');
} else {
if (prev[curr] == val) {
console.log('no change necessary');
} else {
var old = prev[curr];
prev[curr] = val;
console.log('changing modeldata[' + variable + ']: ' + old + ' to ' + prev[curr]);
return prev[curr];
}
}
} else {
return prev[curr];
}
}, modeldata)
You will have
set('curren', 100); // modeldata[curren] is not defined, OK
set('current', 100); // no change necessary, OK
set('current', 120); // changing modeldata[current]: 100 to 120, OK
set('pipeline.0', 42); // changing modeldata[pipeline.0]: 150 to 42, OK
Upvotes: 1
Reputation: 92854
This condition if (modeldata[variable] ....
checks for existance of distinct named property in modeldata
object.
Extend you set
function so it could consider array keys:
var modeldata = {
current: 100,
pipeline: [150,200,210,220]
}
var set = (variable, val, array_key) => {
var prop = (typeof array_key == "number")? modeldata[variable][array_key] : modeldata[variable];
if (prop == undefined) {
console.log('modeldata['+variable+'] is not defined');
} else {
if (prop == val) {
console.log('no change necessary');
} else {
var old = prop;
if (typeof array_key == "number"){
modeldata[variable][array_key] = val;
} else {
modeldata[variable] = val;
}
console.log('changing modeldata['+variable+']: ' + old + ' to ' + modeldata[variable])
}
}
};
set('curren', 100); // modeldata[curren] is not defined, OK
set('current', 100); // no change necessary, OK
set('current', 120); // changing modeldata[current]: 100 to 120, OK
set('pipeline', 42, 0); // m
console.log(modeldata);
// the output:
Object {current: 120, pipeline: Array[4]} .....
current: 120
pipeline: Array[4]
0: 42
1: 200
2: 210
3: 220
length: 4
Upvotes: 0
Reputation: 483
You can refer below code:
var getBothIndexVariables = function (input) {
var openingIndex = input.indexOf('[');
var secondVal = "";
var indexVariable;
if (openingIndex != -1) {
secondVal = input.substring(openingIndex + 1, input.length - 1);
indexVariable = {
firstIndexVariable: input.substring(0,openingIndex),
secondIndexVariable: secondVal,
}
}
return indexVariable;
}
var modeldata = {
current: 100,
pipeline: [150, 200, 210, 220]
}
set = (variable, val) => {
var tempVariable = getBothIndexVariables(variable);
if (tempVariable) {
debugger;
var value = modeldata[tempVariable.firstIndexVariable][tempVariable.secondIndexVariable];
modeldata[tempVariable.firstIndexVariable][tempVariable.secondIndexVariable] = val;
console.log(value);
return;
}
if (modeldata[variable] == undefined) {
console.log('modeldata[' + variable + '] is not defined');
} else {
if (modeldata[variable] == val) {
console.log('no change necessary');
} else {
var old = modeldata[variable];
modeldata[variable] = val;
console.log('changing modeldata[' + variable + ']: ' + old + ' to ' + modeldata[variable])
}
}
}
set('curren', 100); // modeldata[curren] is not defined, OK
set('current', 100); // no change necessary, OK
set('current', 120); // changing modeldata[current]: 100 to 120, OK
set('pipeline[0]', 42); // modeldata[pipeline[0]] is not defined, FAIL
Upvotes: 0
Reputation: 13
I have created a quick and dirty workaround by adding this code at the very beginning of my set
-function:
set = (variable, val) => {
if (variable.indexOf('[')>0 && variable.indexOf(']')>0) {
var old = eval('modeldata.'+variable);
eval('modeldata.'+variable+'='+val);
console.log('changing modeldata.'+variable+': ' + old + ' to ' + val)
return;
}
It works but it doesn't make me feel good to use eval()
. I'd love to see better answers.
Upvotes: 0