I have 3 json arrays, each with information listed in the same format:
Array:
ID:
NAME:
DATA:
ID:
NAME:
DATA:
etc...
My goal is to combine all 3 arrays into one array, and sort and display by NAME by passing the 3 arrays into a function.
The function I've tried is:
Javascript Call:
// to save time I'm just passing the name of the array, I've tried passing
// the full array name as json[0]['DATA'][array_1][0]['NAME'] as well.
combineNames(['array_1','array_2']);
FUNCTION:
function combineNames(names) {
var allNames = []
for (i=0;i<names.length;i++) {
for (j=0;j<json[0]['DATA'][names[i]].length;j++) {
allNames.push(json[0]['DATA'][names[i]][j]['NAME']);
}
}
return allNames.sort();
}
The above gives me the error that NAME is null or undefined.
I've also tried using the array.concat function which works when I hard code it:
var names = [];
var allNames = [];
var names = names.concat(json[0]['DATA']['array_1'],json[0]['DATA']['array_2']);
for (i=0;i<names.length;i++) {
allNames.push(names[i]['NAME']);
}
return allNames.sort();
But I can't figure out how to pass in the arrays into the function (and if possible I would like to just pass in the array name part instead of the whole json[0]['DATA']['array_name'] like I was trying to do in the first function...
you can combine JSON easily with jQuery :
var x ={ a:1, b:2 };
var y ={ a:2, c:3 };
var z ={ b:3, d:4 };
$.extend(x, y, z);
console.dir(x); // now 'x' is all of them combined
If you've got 3 arrays like this:
[{ "id":1, "name":"Bob", "data":1},{ "id":2, "name":"Fred", "data":2 }]
Simply do:
function combine() {
var ar = [];
return ar.concat.apply(ar, arguments).sort(function (a, b) {
var aName = a.NAME;
var bName = b.NAME;
if (aName < bName) {
return -1;
} else if (aName == bName) {
return 0;
} else {
return 1;
};
});
};
Then call it like:
var jointArrays = combine(array1, array2, array3, ...);
However, if your JSON looks like this:
json[0]['DATA'][array_1]
json[0]['DATA'][array_2]
json[0]['DATA'][array_3]
You can simply define combine() as follows, which will be more convenient:
function combine(arrays) {
var ar = [];
return ar.concat.apply(ar, arrays).sort(function (a, b) {
var aName = a.NAME;
var bName = b.NAME;
if (aName < bName) {
return -1;
} else if (aName == bName) {
return 0;
} else {
return 1;
};
});
};
Then call it like:
var jointArrays = combine(json[0].DATA);
If you're wanting an array of just the names, rather than the objects, use the following:
function combine(arrays) {
var ar = [],
ret = [];
ar = ar.concat.apply(ar, arrays);
for (var i=0;i<ar.length;i++) {
ret.push(ar.NAME);
};
return ret.sort();
};
Javascript is case sensitive; make sure it's DATA and not data, and NAME and not name.
Now for a little bit of housekeeping.
In your example, both of your counter variables are being declared as "implied globals", because you're not prefixing them with the var statement (and implied globals are bad). You should use:
for (var i=0;i<something.length;i++) {
//
};
Instead of neglecting the var.
Also, "{}" creates an object. "[]" creates an array. Javascript does not support associative array's; e.g array's with keys that are anything except a number. What you're JSON is returning is an array of objects
"Square notation" and "dot notation" are interchangeable. object["one"] is equivalent to object.one
Square notation is generally used when the key is stored as a variable, or when you're accessing an array.
var key = "one";
object[key]
Hope this helps.
You're redeclaring the allNames variable, emptying it.
Try this:
function combineNames(names) {
var allNames = [];
var data = json[0]['DATA'];
for (arrnames in data) {
for (j=0;j<data[arrnames].length;j++) {
if ('NAME' in data[arrnames]){
allNames.push(data[arrnames]['NAME']);
}
}
}
return allNames.sort();
}
function allNames(names) {
var allNames = [];
for (var i=0;i<names.length;i++) {
for (var j=0;j<json[0]['DATA'][names[i]].length;j++) {
allNames.push(json[0]['DATA'][names[i]][j]['NAME']);
}
}
return allNames.sort();
}
called using:
allNames(['array_1','array_2']);
Seems to work.
Related
I have one object that I had to take apart into two arrays to handle properly.
It looked like this:
{
city:"stuttgart",
street:"randomstreet",
...
}
Since it needs to fit a certain directive I had to convert it to:
[
{key:"city", value:"stuttgart"}
{key:"street", value:"randomstreet"},
...
]
for this I first used
var mapFromObjectWithIndex = function (array) {
return $.map(array, function(value, index) {
return [value];
});
};
var mapFromObjectWithValue = function (array) {
return $.map(array, function(value, index) {
return [index];
});
});
to create two arrays, one containing the old key, the other one is holding the old value. Then I created another, two dimensional array map them into a single array doing this
var mapToArray = function (arrayValue, arrayIndex) {
var tableData = [];
for (var i = 0; i<arrayIndex.length; i++){
tableData[i] = {key:arrayIndex[i] , value:arrayValue[i]};
}
return tableData;
};
(maybe I have already messed up by here, can this be done any easier?)
Now, I use the array (tableData) to display the data in a form. The value fields can be edited. In the end, I want to convert the array (tableData) to its original. (see first object)
Please note, that the original object doesn't only contain strings as values, but can also contain objects as well.
I think conversion can be definitely easier:
var obj = {
city:"stuttgart",
street:"randomstreet",
};
var tableData = Object.keys(obj).map(k => {return {key: k, value: obj[k]}});
console.log(tableData);
var dataBack = {};
tableData.forEach(o => dataBack[o.key] = o.value);
console.log(dataBack);
What do you want to do with objects? Do you want to expand them as well? If yes you can do something like this (and it works with nested objects as well):
var obj = {
city:"stuttgart",
street:"randomstreet",
obj: {a: 'a', b: 'b'},
subObject: {aha: {z: 'z', y: 'y'}}
};
function trasformToTableData(obj) {
if (typeof obj !== 'object') return obj;
return Object.keys(obj).map(k => {return {key: k, value: trasformToTableData(obj[k])}});
}
var tableData = trasformToTableData(obj);
console.log(tableData);
function transformBack(obj) {
if (Array.isArray(obj)) {
var support ={};
for (let i = 0; i < obj.length; i++) {
support[obj[i].key] = transformBack(obj[i].value)
}
return support;
}
return obj;
}
var dataBack = {};
tableData.forEach(o => dataBack[o.key] = transformBack(o.value));
console.log(dataBack);
Let's have some fun and turn our object into iterable to do the job as follows;
var input = {city:"stuttgart", street:"randomstreet", number: "42"};
output = [];
input[Symbol.iterator] = function*(){
var ok = Object.keys(this),
i = 0;
while (i < ok.length) yield {key : ok[i], value: this[ok[i++]]};
};
output = [...input];
console.log(output);
This function will map your object to an array when you call objVar.mapToArray(), by using Object.keys() and .map()
Object.prototype.mapToArray = function() {
return Object.keys(this).map(function(v) {
return { key: v, value: this[v] };
}.bind(this));
}
I would do something like this:
var dataObj = {
city:"stuttgart",
street:"randomstreet",
};
function toKeyValue(obj) {
var arr = [];
for (var key in obj) {
if(obj.hasOwnProperty(key)) {
arr.push({'key': key, 'value': obj[key]});
}
}
return arr;
}
var arrayKeyValue = toKeyValue(dataObj);
console.log(arrayKeyValue);
I have 2 objects that I need to merge and keep all properties in tact, tried with jQuery $.extend but I cant get it to work . I tried all posts with how to merge javascript objects but simply cant get this to work.
var thz_icon_source = {"Spinners":["spinnericon1","spinnericon2"],"Awesome":["awesomeicon1","awesomeicon2"]};
var fa_icon_source = {"Spinners":["faspinner1","faspinner2"],"Awesome":["faawesome1","faawesome2"]};
var new_source ={};
$.extend(new_source,fa_icon_source,thz_icon_source);
console.log(thz_icon_source);
console.log(fa_icon_source);
console.log(new_source);
desired output should be like
{
"Spinners":["faspinner1","faspinner2","spinnericon1","spinnericon2"],
"Awesome":["faawesome1","faawesome2","awesomeicon1","awesomeicon2"]
}
This post Merge two json/javascript arrays in to one array has a simple object mine is not same as that one.
Demo
function mergeJSON(json1,json2)
{
var result = json1 ;
for (var prop in json2)
{
if (json2.hasOwnProperty(prop))
{
result[prop] = result[prop].concat(json2[prop]);
}
}
return result;
}
$.extend merges in missing properties, it doesn't combine the properties that are in common. You need to write a loop.
var thz_icon_source = {
"Spinners": ["spinnericon1", "spinnericon2"],
"Awesome": ["awesomeicon1", "awesomeicon2"]
};
var fa_icon_source = {
"Spinners": ["faspinner1", "faspinner2"],
"Awesome": ["faawesome1", "faawesome2"]
};
var new_source = {};
// First add in the new elements from thz_icon_source
$.extend(new_source, fa_icon_source, thz_icon_source);
// Now merge the common elements
$.each(fa_icon_source, function(k, e) {
if (thz_icon_source.hasOwnProperty(k)) {
new_source[k] = e.concat(thz_icon_source[k]);
}
});
console.log(thz_icon_source);
console.log(fa_icon_source);
console.log(new_source);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You can use this prototype to merge 2 or more objects the way you want it:
Object.prototype.assignDeep = function() {
var self = this;
Object.keys(arguments).forEach(obj => {
Object.keys(self).forEach(val => {
if (arguments[obj].hasOwnProperty(val)) {
var tmp = arguments[obj][val] instanceof Array ? arguments[obj][val] : [arguments[obj][val]];
self[val] = self[val].concat(tmp);
}
});
});
return self;
}
var thz_icon_source = {"Spinners":["spinnericon1","spinnericon2"],"Awesome":["awesomeicon1","awesomeicon2"]};
var fa_icon_source = {"Spinners":["faspinner1","faspinner2"],"Awesome":["faawesome1","faawesome2"]};
var b = thz_icon_source.assignDeep(fa_icon_source);
console.log(b);
You should use a loops with .concat():
function objectConcatArrays(){
var a = arguments, o = {};
for(var i=0,l=a.length; i<l; i++){
for(var p in a[i]){
if(p in o){
o[p] = o[p].concat(a[i][p]);
}
else{
o[p] = a[i][p];
}
}
}
return o;
}
var thz_icon_source = {"Spinners":["spinnericon1","spinnericon2"],"Awesome":["awesomeicon1","awesomeicon2"]};
var fa_icon_source = {"Spinners":["faspinner1","faspinner2"],"Awesome":["faawesome1","faawesome2"]};
var res = objectConcatArrays(thz_icon_source, fa_icon_source);
console.log(res);
Each argument represents an Object of Arrays. Add more if you want.
I have array object(x) that stores json (key,value) objects. I need to make sure that x only takes json object with unique key. Below, example 'id' is the key, so i don't want to store other json objects with 'item1' key.
x = [{"id":"item1","val":"Items"},{"id":"item1","val":"Items"},{"id":"item1","val":"Items"}]
var clickId = // could be "item1", "item2"....
var found = $.inArray(clickId, x); //
if(found >=0)
{
x.splice(found,1);
}
else{
x.push(new Item(clickId, obj)); //push json object
}
would this accomplish what you're looking for? https://jsfiddle.net/gukv9arj/3/
x = [
{"id":"item1","val":"Items"},
{"id":"item1","val":"Items"},
{"id":"item2","val":"Items"}
];
var clickId = [];
var list = JSON.parse(x);
$.each(list, function(index, value){
if(clickId.indexOf(value.id) === -1){
clickId.push(value.id);
}
});
You can't use inArray() because you are searching for an object.
I'd recommend rewriting a custom find using Array.some() as follows.
var x = [{"id":"item1","val":"Items"},{"id":"item1","val":"Items"},{"id":"item1","val":"Items"}]
var clickId = "item1";
var found = x.some(function(value) {
return value.id === clickId;
});
alert(found);
Almost 6 years later i ended up in this question, but i needed to fill a bit more complex array, with objects. So i needed to add something like this.
var values = [
{value: "value1", selected: false},
{value: "value2", selected: false}
//there cannot be another object with value = "value1" within the collection.
]
So I was looking for the value data not to be repeated (in an object's array), rather than just the value in a string's array, as required in this question. This is not the first time i think in doing something like this in some JS code.
So i did the following:
let valueIndex = {};
let values = []
//I had the source data in some other and more complex array.
for (const index in assetsArray)
{
const element = assetsArray[index];
if (!valueIndex[element.value])
{
valueIndex[element.value] = true;
values.push({
value: element.value,
selected: false
});
}
}
I just use another object as an index, so the properties in an object will never be repated. This code is quite easy to read and surely is compatible with any browser. Maybe someone comes with something better. You are welcome to share!
Hopes this helps someone else.
JS objects are great tools to use for tracking unique items. If you start with an empty object, you can incrementally add keys/values. If the object already has a key for a given item, you can set it to some known value that is use used to indicate a non-unique item.
You could then loop over the object and push the unique items to an array.
var itemsObj = {};
var itemsList = [];
x = [{"id":"item1","val":"foo"},
{"id":"item2","val":"bar"},
{"id":"item1","val":"baz"},
{"id":"item1","val":"bez"}];
for (var i = 0; i < x.length; i++) {
var item = x[i];
if (itemsObj[item.id]) {
itemsObj[item.id] = "dupe";
}
else {
itemsObj[item.id] = item;
}
}
for (var myKey in itemsObj) {
if (itemsObj[myKey] !== "dupe") {
itemsList.push(itemsObj[myKey]);
}
}
console.log(itemsList);
See a working example here: https://jsbin.com/qucuso
If you want a list of items that contain only the first instance of an id, you can do this:
var itemsObj = {};
var itemsList = [];
x = [{"id":"item1","val":"foo"},
{"id":"item2","val":"bar"},
{"id":"item1","val":"baz"},
{"id":"item1","val":"bez"}];
for (var i = 0; i < x.length; i++) {
var item = x[i];
if (!itemsObj[item.id]) {
itemsObj[item.id] = item;
itemsList.push(item);
}
}
console.log(itemsList);
This is late but I did something like the following:
let MyArray = [];
MyArray._PushAndRejectDuplicate = function(el) {
if (this.indexOf(el) == -1) this.push(el)
else return;
}
MyArray._PushAndRejectDuplicate(1); // [1]
MyArray._PushAndRejectDuplicate(2); // [1,2]
MyArray._PushAndRejectDuplicate(1); // [1,2]
This is how I would do it in pure javascript.
var x = [{"id":"item1","val":"Items"},{"id":"item1","val":"Items"},{"id":"item1","val":"Items"}];
function unique(arr, comparator) {
var uniqueArr = [];
for (var i in arr) {
var found = false;
for (var j in uniqueArr) {
if (comparator instanceof Function) {
if (comparator.call(null, arr[i], uniqueArr[j])) {
found = true;
break;
}
} else {
if (arr[i] == uniqueArr[j]) {
found = true;
break;
}
}
}
if (!found) {
uniqueArr.push(arr[i]);
}
}
return uniqueArr;
};
u = unique(x, function(a,b){ return a.id == b.id; });
console.log(u);
y = [ 1,1,2,3,4,5,5,6,1];
console.log(unique(y));
Create a very readable solution with lodash.
x = _.unionBy(x, [new Item(clickId, obj)], 'id');
let x = [{id:item1,data:value},{id:item2,data:value},{id:item3,data:value}]
let newEle = {id:newItem,data:value}
let prev = x.filter(ele=>{if(ele.id!=new.id)return ele);
newArr = [...prev,newEle]
Let's say I have a Javascript associative array (a.k.a. hash, a.k.a. dictionary):
var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;
How can I iterate over the keys in sorted order? If it helps simplify things, I don't even need the values (they're all just the number 1).
You can use the Object.keys built-in method:
var sorted_keys = Object.keys(a).sort()
(Note: this does not work in very old browsers not supporting EcmaScript5, notably IE6, 7 and 8. For detailed up-to-date statistics, see this table)
You cannot iterate over them directly, but you can find all the keys and then just sort them.
var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;
function keys(obj)
{
var keys = [];
for(var key in obj)
{
if(obj.hasOwnProperty(key))
{
keys.push(key);
}
}
return keys;
}
keys(a).sort(); // ["a", "b", "z"]
However there is no need to make the variable 'a' an array. You are really just using it as an object and should create it like this:
var a = {};
a["key"] = "value";
you could even prototype it onto object:
Object.prototype.iterateSorted = function(worker)
{
var keys = [];
for (var key in this)
{
if (this.hasOwnProperty(key))
keys.push(key);
}
keys.sort();
for (var i = 0; i < keys.length; i++)
{
worker(this[ keys[i] ]);
}
}
and the usage:
var myObj = { a:1, b:2 };
myObj.iterateSorted(function(value)
{
alert(value);
}
I agree with Swingley's answer, and I think it is an important point a lot of these more elaborate solutions are missing. If you are only concerned with the keys in the associative array and all the values are '1', then simply store the 'keys' as values in an array.
Instead of:
var a = { b:1, z:1, a:1 };
// relatively elaborate code to retrieve the keys and sort them
Use:
var a = [ 'b', 'z', 'a' ];
alert(a.sort());
The one drawback to this is that you can not determine whether a specific key is set as easily. See this answer to javascript function inArray for an answer to that problem. One issue with the solution presented is that a.hasValue('key') is going to be slightly slower than a['key']. That may or may not matter in your code.
There's no concise way to directly manipulate the "keys" of a Javascript object. It's not really designed for that. Do you have the freedom to put your data in something better than a regular object (or an Array, as your sample code suggests)?
If so, and if your question could be rephrased as "What dictionary-like object should I use if I want to iterate over the keys in sorted order?" then you might develop an object like this:
var a = {
keys : new Array(),
hash : new Object(),
set : function(key, value) {
if (typeof(this.hash[key]) == "undefined") { this.keys.push(key); }
this.hash[key] = value;
},
get : function(key) {
return this.hash[key];
},
getSortedKeys : function() {
this.keys.sort();
return this.keys;
}
};
// sample use
a.set('b',1);
a.set('z',1);
a.set('a',1);
var sortedKeys = a.getSortedKeys();
for (var i in sortedKeys) { print(sortedKeys[i]); }
If you have no control over the fact that the data is in a regular object, this utility would convert the regular object to your fully-functional dictionary:
a.importObject = function(object) {
for (var i in object) { this.set(i, object); }
};
This was a object definition (instead of a reusable constructor function) for simplicity; edit at will.
Get the keys in the first for loop, sort it, use the sorted result in the 2nd for loop.
var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;
var b = [];
for (k in a) b.push(k);
b.sort();
for (var i = 0; i < b.length; ++i) alert(b[i]);
You can use the keys function from the underscore.js library to get the keys, then the sort() array method to sort them:
var sortedKeys = _.keys(dict).sort();
The keys function in the underscore's source code:
// Retrieve the names of an object's properties.
// Delegates to **ECMAScript 5**'s native `Object.keys`
_.keys = nativeKeys || function(obj) {
if (obj !== Object(obj)) throw new TypeError('Invalid object');
var keys = [];
for (var key in obj) if (_.has(obj, key)) keys.push(key);
return keys;
};
// Shortcut function for checking if an object has a given property directly
// on itself (in other words, not on a prototype).
_.has = function(obj, key) {
return hasOwnProperty.call(obj, key);
};
<script type="text/javascript">
var a = {
b:1,
z:1,
a:1
}; // your JS Object
var keys = [];
for (key in a) {
keys.push(key);
}
keys.sort();
var i = 0;
var keyslen = keys.length;
var str = '';
//SORTED KEY ITERATION
while (i < keyslen) {
str += keys[i] + '=>' + a[keys[i]] + '\n';
++i;
}
alert(str);
/*RESULT:
a=>1
b=>1
z=>1
*/
</script>
var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;
var keys=Object.keys(a).sort();
for(var i=0,key=keys[0];i<keys.length;key=keys[++i]){
document.write(key+' : '+a[key]+'<br>');
}
I really like #luke-schafer's prototype idea, but also hear what he is saying about the issues with prototypes. What about using a simple function?
function sortKeysAndDo( obj, worker ) {
var keys = Object.keys(obj);
keys.sort();
for (var i = 0; i < keys.length; i++) {
worker(keys[i], obj[keys[i]]);
}
}
function show( key, value ) {
document.write( key + ' : ' + value +'<br>' );
}
var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;
sortKeysAndDo( a, show);
var my_object = { 'c': 3, 'a': 1, 'b': 2 };
sortKeysAndDo( my_object, show);
This seems to eliminate the issues with prototypes and still provide a sorted iterator for objects. I am not really a JavaScript guru, though, so I'd love to know if this solution has hidden flaws I missed.
I am trying to create a javascript object like
var allUserExpiry={};
allUserExpiry[aData.userId][aData.courseId][aData.uscId] = aData;
But I am getting an error like allUserExpiry[aData.userId] undefined.
Is there a way, whereby I can set multi-level JS-Object keys? or is it important that I should go by doing allUserExpiry[aData.userId]={}, then allUserExpiry[aData.userId][aData.courseId]={} ?
Please let me know if there are any utility functions available for the same.
No, there is no way to set "multilevel keys". You need to initialize each object before trying to add properties to it.
var allUserExpiry = {};
allUserExpiry[aData.userId] = {}
allUserExpiry[aData.userId][aData.courseId] = {}
allUserExpiry[aData.userId][aData.courseId][aData.uscId] = aData;
Using Computed property names from ES6, it is possible to do:
var allUserExpiry = {
[aData.userId] = {
[aData.courseId]: {
[aData.uscId]: aData
}
}
};
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names
Simply use loadash,
let object = {};
let property = "a.b.c";
let value = 1;
_.set(object, property, value); // sets property based on path
let value = _.get(object, property, default); // gets property based on path
Or you can do it:
function setByPath(obj, path, value) {
var parts = path.split('.');
var o = obj;
if (parts.length > 1) {
for (var i = 0; i < parts.length - 1; i++) {
if (!o[parts[i]])
o[parts[i]] = {};
o = o[parts[i]];
}
}
o[parts[parts.length - 1]] = value;
}
And use:
setByPath(obj, 'path.path2.path', someValue);
This approach has many weak places, but for fun... :)
Why not just do this?
var allUserExpiry={};
allUserExpiry[aData.userId] = {aData.courseId: {aData.uscId: aData}};
I have a pretty hacky but short way of doing it in IE9+ as well as real browsers.
Given var path = 'aaa.bbb.ccc.ddd.eee'; where path is what your intending to make into an object and var result = {}; will will create the object {aaa: {bbb: {ccc: {ddd: {eee: {}}}}}
result = {}
path.split('.').reduce(function(prev, e) {
var newObj = {};
prev[e] = newObj;
return newObj;
}, result);
will store the object in result.
How it works:
split('.') converts the input into ['aaa', 'bbb', 'ccc', 'ddd', 'eee']
reduce(function (...) {...}, result) runs through the array created by split, and for each entry will pass along a returned value to the next one. In our case we pass the new object through after adding the new object to the old one. This creates a chain of objects. reduce returns the last object you return inside of it, so we have to defined result beforehand.
This relies on using references so it won't be immediately clear how it works if you're expecting your code to be maintained by anyone else and should probably be avoided to be honest, but it works at least.
You can also use the following to create the initial structure:
var x = function(obj, keys) {
if (!obj) return;
var i, t;
for (i = 0; i < keys.length; i++) {
if (!t) {
t = obj[keys[i]] = {};
} else {
t[keys[i]] = {};
t = t[keys[i]];
}
}
};
var a = {};
x(a, ['A', 'B', 'C', 'D', 'E', 'F']);
Another approach without strings or array as argument.
function fillObject() {
var o = arguments[0];
for(var i = 1; i < arguments.length-1; i++) {
if(!o.hasOwnProperty(arguments[i])) {
o[arguments[i]] = {};
}
if(i < arguments.length-2) {
o = o[arguments[i]];
}else {
o[arguments[i]] = arguments[i+1]
}
}
}
var myObj = {"foo":{}};
fillObject(myObj,"back","to","the","future",2);
console.log(JSON.stringify(myObj));
// {"foo":{},"back":{"to":{"the":{"future":2}}}}
But I wouldn't use it :-) It's just for fun.
Because I don't like too much intelligent algorithm. (If it was in this category)
Using lodash you can do this easily (node exists and empty check for that node)..
var lodash = require('lodash-contrib');
function invalidateRequest(obj, param) {
var valid = true;
param.forEach(function(val) {
if(!lodash.hasPath(obj, val)) {
valid = false;
} else {
if(lodash.getPath(obj, val) == null || lodash.getPath(obj, val) == undefined || lodash.getPath(obj, val) == '') {
valid = false;
}
}
});
return valid;
}
Usage:
leaveDetails = {
"startDay": 1414998000000,
"endDay": 1415084400000,
"test": { "test1" : 1234 }
};
var validate;
validate = invalidateRequest(leaveDetails, ['startDay', 'endDay', 'test.test1']);
it will return boolean.
Another solution using reduce function (thanks Brian K).
Here we created a get/set to general proposes. The first function return the value in any level. The key is splited considering the separator. the function return the value refered from last index in the key's array
The second function will set the new value considering the last index of the splited key
the code:
function getObjectMultiLevelValue(_array,key,separator){
key = key.split(separator || '.');
var _value = JSON.parse(JSON.stringify(_array));
for(var ki in key){
_value = _value[key[ki]];
}
return _value;
}
function setObjectMultiLevelValue(_array,key,value,forcemode,separator){
key.split(separator || '.').reduce(function(prev, currKey, currIndex,keysArr) {
var newObj = {};
if(prev[currKey] && !forcemode){
newObj = prev[currKey];
}
if(keysArr[keysArr.length-1] == currKey){
newObj = value;
prev[currKey] = newObj;
}
prev[currKey] = newObj;
return newObj;
}, _array);
return _array;
}
//testing the function
//creating an array
var _someArray = {a:'a',b:'b',c:{c1:'c1',c2:{c21:'nothing here...'}}};
//a multilevel key to test
var _key = 'a,a1,a21';
//any value
var _value = 'new foo in a21 key forcing replace old path';
//here the new value will be inserted even if the path exists (forcemode=true). Using comma separator
setObjectMultiLevelValue(_someArray,_key,_value,true,',');
console.log('_someArray:');
console.log(JSON.stringify(_someArray));
//inserting another value in another key... using default separator
_key = 'c.c2.c21';
_value = 'new foo in c21 key';
setObjectMultiLevelValue(_someArray,_key,_value);
console.log('_someArray:');
console.log(JSON.stringify(_someArray));
//recovering the saved value with different separators
_key = 'a,a1,a21';
console.log(getObjectMultiLevelValue(_someArray,_key,','));
_key = 'c.c2.c21';
console.log(getObjectMultiLevelValue(_someArray,_key));
Let assume our object is
const data = {
//some other data
userInfo: {},
};
First, define a new property of that object
data.userInfo.vehicle = {};
then simply
data.userInfo.vehicle.vehicleType = state.userInfo.vehicleType;