Create a json array dynamically - javascript

I have an array of objects like this below,
var A = [
{
"111": ["A", "B", "C"]
},
{
"222": ["D", "E", "F"]
}
];
I would like to create a new array dynamically in the format as shown below using js or jQuery.
key in array A should be mapping to attribute text of AA and value should be to children as given below
var AA = [
{
"text": "111",
"state": "open",
"children": [
{
"text": "A"
},
{
"text": "B"
},
{
"text": "C"
}]
},
{
"text": "222",
"state": "open",
"children": [
{
"text": "D"
},
{
"text": "E"
},
{
"text": "F"
}]
}];
How can I accomplish this ? Any thoughts would be helpful
Thanks for all of your suggestions and help.
But Right now I would like to change variable A and input in the format below,
how can i accomplish the same as before.
var A = {"1":["1_1","1_2","1_3"],
"2":["2_1","2_2"],
"3":["3_1"],
"4":["4_1"],
"5":["5_1","5_2"]};

You can map A to AA using Array.prototype.map() (twice).
var AA = A.map(function(item) {
var key = Object.keys(item)[0]; // this will be reliable only because each item has one property.
return {
'text': key,
'state': 'open',
'children': item[key].map(function(child) {
return { 'text': child };
})
};
});
fiddle

My answer is too long, but its still understandable
var A = [
{"111":["A","B","C"]},
{"222":["D","E","F"]}
];
console.log(A);
A = superGenerator(A);
console.log(A);
function superGenerator(data){
var dataF = [];
var children = [];
for (var i = data.length - 1; i >= 0; i--) {
children[i] = [];
for (var [key, val] of iterate_object(data[i])) {
for (var j = val.length - 1; j >= 0; j--) {
children[i][j] = [];
children[i][j] = {
text : val[j]
}
};
}
dataF[i] = {
text : Object.keys(data[i])[0],
state : 'open',
children : children[i]
}
};
return dataF;
}
function* iterate_object(o) {
var keys = Object.keys(o);
for (var i=0; i<keys.length; i++) {
yield [keys[i], o[keys[i]]];
}
}
You can try it by click Run,
Cheers

Try this :
var A = [
{
"111": ["A", "B", "C"]
},
{
"222": ["D", "E", "F"]
}
];
var AA = A.map(item => {
return {
"text": Object.keys(item)[0],
"state": "open",
"children": item[Object.keys(item)[0]].map(elem => { return {"text": elem} })
}
});
console.log(AA);

You can use array#map to iterate through your array, for each object, iterate all its keys and generate the corresponding object.
var arr = [ { "111": ["A", "B", "C"] }, { "222": ["D", "E", "F"] } ],
result = arr.map(o => Object.keys(o).reduce((r,k) => {
return {
text : k,
state : 'open',
children : o[k].map(text => ({text}))
};
},{}));
console.log(result);

Related

Single variable to stand in for multiple key names - javascript

I have an array, something like this:
array =
[
{
"type": "apple",
"color": "red",
"id": "redApple"
},
{
"type": "grape",
"color": "green",
"id": "greenGrape",
"options": [
{
"bunchName": "bunch1",
"size": "8"
},
{
"bunchName": "bunch2",
"size": "10"
},
{
"bunchName": "bunch3",
"size": "5"
}
]
}
]
I have a function that searches for values in the array.
function findValue (index, key) {
return array[index][key];
}
var value = findValue(0, "id");
// returns redApple
Is there a way I could pass a single argument to the function if I wanted to find something deeper in the array? For example, if I wanted to find "bunchName" could I pass it something like 1, "options[0].bunchName" and get back "bunch1"?
I want a function that can handle multiple keys. In my real project sometimes I'm looking for something on the first level, sometimes I'm looking on the second level, sometimes the third level, etc.
jQuery can be used if for some reason that would help.
You could take the string, replace the brackets, split the string and reduce the path for the result. The function uses a default object for missing or not given properties.
function getValue(object, path) {
return path
.replace(/\[/g, '.')
.replace(/\]/g, '')
.split('.')
.reduce(function (o, k) { return (o || {})[k]; }, object);
}
function findValue(index, path) {
return getValue(array[index], path);
}
var array = [{ type: "apple", color: "red", id: "redApple" }, { type: "grape", color: "green", id: "greenGrape", options: [{ bunchName: "bunch1", size: "8" }, { bunchName: "bunch2", size: "10" }, { bunchName: "bunch3", size: "5" }] }];
console.log(findValue(1, "options[0].bunchName"));
From what I understand, output of findValue(object, "bunchName"); should be "bunch3", where object is array in OP's example.
var object =
[
{
"type": "apple",
"color": "red",
"id": "redApple"
},
{
"type": "grape",
"color": "green",
"id": "greenGrape",
"options": [
{
"bunchName": "bunch1",
"size": "8"
},
{
"bunchName": "bunch2",
"size": "10"
},
{
"bunchName": "bunch3",
"size": "5"
}
]
}
]
var findValue = (object, key) => {
var resultValue;
var rec = (currentObj) => {
if(currentObj && typeof currentObj === "object"){
for(let curKey in currentObj){
if (curKey === key){
resultValue = currentObj[curKey];
}else{
rec(currentObj[curKey]);
}
}
}
}
rec(object);
return resultValue;
}
console.log(findValue(object, "bunchName"));
You could add a function that takes an object and a key and returns object[key] and then split your key string into a list of individual keys by the dot. Then you could traverse the list of keys and use the function to get the value for each level in your object:
Totally untested code I just whipped up:
function valueByKey(obj, key) {
if (obj) {
return obj[key];
}
}
function findValue(index, key) {
const keys = key.split('.');
let value = array[index];
for (let i = 0; i < keys.length; i++) {
value = valueByKey(value, keys[i]);
}
return value;
}
Non-recurrent solution:
var array = [
{
'a': {
'b': 1
}
}
];
function findValue(index, key) {
var keys = key.split('.');
var tmp = array[index];
for (var i = 0; i < keys.length; i++) {
if (!tmp.hasOwnProperty(keys[i]) || typeof tmp !== 'object') {
// throw an exception, or return default value – property not found.
}
tmp = tmp[keys[i]];
}
return tmp;
}
findValue(0, 'a.b');

check to see if all objects in an array has a common property

I have an array of objects which I am trying to loop over and check for a common key if it exists for all objects. if the specific key does not exist for all objects I return false.
Here is my code
var x = [{
"item": "alpha",
"value": "red"
}, {
"item": "beta",
"value": "blue"
}, {
"item": "beta",
"value": "gama"
}]
function test(obj) {
var count = 0;
var out = false;
for (var i = 0; i < obj.length; i++) {
if (obj[i].hasOwnProperty('value')) {
count = i;
}
}
if (count == obj.length) {
out = true
}
}
console.log(test(x))
I am getting undefined. Cant figure out what am I missing here
A really simple way to do this is to use Array#every like this
var x = [{
"item": "alpha",
"value": "red"
}, {
"item": "beta",
"value": "blue"
}, {
"item": "beta",
"value": "gama"
}]
function test(obj) {
return obj.every(a => a.hasOwnProperty("value"));
}
console.log(test(x))
Update
As rightfully mentioned by this comment first.
Here can be the simple solution for this object:
var x = [{
"item": "alpha",
"value": "red"
}, {
"item": "beta",
"value": "blue"
}, {
"item": "beta",
"value": "gama"
}];
function test(obj) {
var keyCount = 0;
obj.forEach(function (item, index) {
item.hasOwnProperty('value') && ++keyCount;
});
return keyCount == obj.length;
}
console.log(test(x));
Here is my implementation, which finds every matching key, even nested keys, given a set of objects:
function recurse_obj(obj, cb, _stack = []) {
for (var k in obj) {
cb(k, obj[k], _stack);
if (obj.hasOwnProperty(k) && (obj[k] instanceof Object)) {
_stack.push(k);
recurse_obj(obj[k], cb, _stack);
_stack.pop();
}
}
}
function obj_all_keys(obj) {
var tmp = [];
recurse_obj(obj, (k, v, stack) => {
var ext = (stack.length) ? "." : "";
tmp.push(stack.join(".").concat(ext, k));
});
return tmp;
}
function key_intersection(...objs) {
var lookup = {};
objs.forEach(o => {
obj_all_keys(o).forEach(k => {
if (k in lookup === false)
lookup[k] = 0;
lookup[k]++;
});
});
for (var k in lookup)
if (lookup[k] !== objs.length)
delete lookup[k];
return lookup;
}
Here is the calling code:
var me = { name: { first: "rafael", last: "cepeda" }, age: 23, meta: { nested: { foo: { bar: "hi" } } } };
console.log(key_intersection(me, { name: { first: "hi" } }));
Output: { name: 2, 'name.first': 2 }
The object returned includes only the keys that are found in all the objects, the set intersection, the counts are from book-keeping, and not removed in the callee for performance reasons, callers can do that if need be.
Keys that are included in other nested keys could be excluded from the list, because their inclusion is implied, but I left them there for thoroughness.
Passing a collection (array of objects) is trivial:
key_intersection.apply(this, collection);
or the es6 syntax:
key_intersection(...collection);

How to get an JSON Object based in key using jquery

I'm using jsTree and have tree an structured JSON object.
[{
"id": 1,
"text": "TEXT_ONE",
"children": [
{
"id": 2,
"text": "TEXT_TWO",
"children": [
{
"id": 3,
"text": "TEXT_THREE",
"children": [
]
},
{
"id": 4,
"text": "TEXT_FOUR",
"children": [
]
}
]
},
{
"id": 5,
"text": "TEXT_FIVE",
"children": [
]
}
]
},
{
"id": 6,
"text": "TEXT_SIX",
"children": [ ]
}]
I want to get the the object based on the "id" of the object.
For example if i have a function getIdFromTree(3) it will return me the JSON object as following:
{
"id": 3,
"text": "TEXT_THREE",
"children": []
},
How I do that in Javascript/JQuery?
Try this
function getObjById (tree, id) {
if(tree.id === id) {
return tree;
}
if(tree.children) {
for(var i = 0, l = tree.children.length; i < l; i++) {
var returned = getObjById(tree.children[i], id);
if(returned) {
// so that the loop doesn't keep running even after you find the obj
return returned;
}
}
}
}
Call this as follows
getObjById({children: tree}, 3); // tree is the array object above.
function findById (tree, id) {
var result, i;
if (tree.id && tree.id === id) {
result = tree;
// Revalidate array list
} else if (tree.length) {
for (i = 0; i < tree.length; i++) {
result = findById(tree[i], id);
if (result) {
break;
}
}
// Check childrens
} else if (tree.children) {
result = findById(tree.children, id);
}
return result;
}
Use filter Methode off Array
data.filter(function (obj){ obj.id== 3});
try this.... Es6
function *getObjectById(data, id) {
if (!data) return;
for (let i = 0; i< data.length; i++){
let val = data[i];
if (val.id === id) yield val;
if (val.children) yield *getObjectById(val.children , id);
}
}
now
getObjectById(arrayOfObjects, id).next().value;
try this with most effective and efficient way..
function getObjById (tree, id) {
for(var i= 0;i<tree.length;i++)
{
if(tree[i].id===id)
{
return tree[i];
}
if(tree[i].children)
{
var returned = getObjById(tree[i].children,id);
if(returned!= undefined)
return returned;
}
}
};
link:
https://jsfiddle.net/aa7zyyof/14/

AngularJS: Remove duplicate objects and reorder an array by value

I am using a json, this is the structure:
{ "variants": [
{ "capacity":"A", "color":"1" },
{ "capacity":"A", "color":"2" },
{ "capacity":"B", "color":"3" }
]};
Using angular.forEach or another method, I would like to display data no repeated, reordered it and related it by "capacity", something like this (a new array):
$scope.newArray = [
{ "capacity":"A", "color1":"1", "color2":"2" },
{ "capacity":"B", "color_1":"3" }
];
It is possible an angular way or simply javascript, I need help!
a = { 'variants': [
{'capacity': 'A','color': '1'},
{'capacity': 'A','color': '2'},
{'capacity': 'B','color': '3'},
]};
b = a.variants
c = b.reduce(function (prev, crt) {
prev[crt.capacity] = (prev[crt.capacity] || [
]).concat(crt.color)
return prev;
}, {})
// c is now {"A": ["1","2"], "B": ["3"]}
d = []
for (var name in c) {
if (c.hasOwnProperty(name)) {
f = {
'capacity': name
}
c[name].forEach(function (e) {
f['color' + e] = e;
})
// f is {"capacity": "A", "color1": "1","color2": "2"}
// and then {"capacity": "B", "color3": "3"}
d = d.concat(f)
}
}
// d is [{"capacity": "A", "color1": "1","color2": "2"},
// {"capacity": "B", "color3": "3"}]

How to map a javascript array to another javascript array

I have a constructor in JavaScript which contains 2 properties Key and Values array:
function Test(key, values) {
this.Key = key;
this.Values = values.map(values);
}
Then I created an array of Test objects:
var testObjectArray = [];
testObjectArray.push(new Test(1, ['a1','b1']), new Test(2, ['a1','b2']));
Now I want to map the testObjectArray to single key-value pair array which will be similar to :
[
{ "Key" : "1", "Value" : "a1" },
{ "Key" : "1", "Value" : "b1" },
{ "Key" : "2", "Value" : "a2" },
{ "Key" : "2", "Value" : "b2" },
]
How can I achieve this using array's map function?
I guess you are misunderstanding map(). Here is a very simple example:
a = [1, 2, 3]
b = a.map(function (i) { return i + 1 })
// => [2, 3, 4]
Here is the MDN documentation for map: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map. So you should rethink the usage of map in your case. By the way - your example is not working, because values is not a function.
Here is a possible solution:
res = [];
a = [['a1','b1'],['a1','b2']];
for (var i = 0; i < a.length; ++i) {
for(var j = 0; j < a[i].length; ++j) {
res.push({"Key": i + 1 , "Value" : a[i][j]});
}
}
I'm sure there are other ways, but here's something with plain Javascript that does what you want:
http://jsfiddle.net/KXBRw/
function Test(key, values) {
this.Key = key;
this.Values = values;//values.map(values);
}
function getCombinedTests(testObjectArray) {
var all = [];
for (var i = 0; i < testObjectArray.length; i++) {
var cur = testObjectArray[i];
for (var j = 0; j < cur.Values.length; j++) {
all.push({"Key": ""+cur.Key, "Value": cur.Values[j]});
}
}
return all;
}
var testObjectArray1 = [];
testObjectArray1.push(new Test(1, ['a1','b1']), new Test(2, ['a1','b2']));
var combined = getCombinedTests(testObjectArray1);
console.log(combined);
You could use .reduce(), .concat() and .map() for this.
var result = testObjectArray.reduce(function(res, obj) {
return res.concat(obj.Values.map(function(val) {
return {"Key":obj.Key, "Value":val};
}));
}, []);
Not sure what values.map(values); was supposed to do though.
DEMO: http://jsfiddle.net/BWNGr/
[
{
"Key": 1,
"Value": "a1"
},
{
"Key": 1,
"Value": "b1"
},
{
"Key": 2,
"Value": "a1"
},
{
"Key": 2,
"Value": "b2"
}
]
If you're super strict about not creating unnecessary Arrays, you can tweak it a little and use .push() instead of .concat().
var result = testObjectArray.reduce(function(res, obj) {
res.push.apply(res, obj.Values.map(function(val) {
return {"Key":obj.Key, "Value":val};
}));
return res;
}, []);
DEMO: http://jsfiddle.net/BWNGr/1/
You can achieve this by using the following for each loop where each key value pair will be pushed to an array.
var mapped = [];
$.each(testObjectArray, function(key, value) {
for(x in value.Values) {
mapped.push({
Key: value.Key,
Value: x
});
}
});

Categories