Finding objects in a nested array along with their position - javascript

I've taken the following sample from a different question. And I am able to identify the object. But I also need to find our the position of that object. For example:
var arr = [{
Id: 1,
Categories: [{
Id: 1
},
{
Id: 2
},
]
},
{
Id: 2,
Categories: [{
Id: 100
},
{
Id: 200
},
]
}
]
If I want to find the object by the Id of the Categories, I can use the following:
var matches = [];
var needle = 100; // what to look for
arr.forEach(function(e) {
matches = matches.concat(e.Categories.filter(function(c) {
return (c.Id === needle);
}));
});
However, I also need to know the position of the object in the array. For example, if we are looking for object with Id = 100, then the above code will find the object, but how do I find that it's the second object in the main array, and the first object in the Categories array?
Thanks!

Well, if every object is unique (only in one of the categories), you can simply iterate over everything.
var arr = [{
Id: 1,
Categories: [{Id: 1},{Id: 2}]
},
{
Id: 2,
Categories: [{Id: 100},{Id: 200}]
}
];
var needle = 100;
var i = 0;
var j = 0;
arr.forEach(function(c) {
c.Categories.forEach(function(e) {
if(e.Id === needle) {
console.log("Entry is in position " + i + " of the categories and in position " + j + " in its category.");
}
j++;
});
j = 0;
i++;
});

function findInArray(needle /*object*/, haystack /*array of object*/){
let out = [];
for(let i = 0; i < haystack.lenght; i++) {
if(haystack[i].property == needle.property) {
out = {pos: i, obj: haystack[i]};
}
}
return out;
}
if you need the position and have to filter over an property of the object you can use a simple for loop. in this sample your result is an array of new object because there can be more mathches than 1 on the value of the property.
i hope it helps

Iterate over the array and set index in object where match found
var categoryGroups = [{
Id : 1,
Categories : [{
Id : 1
}, {
Id : 2
},
]
}, {
Id : 2,
Categories : [{
Id : 100
}, {
Id : 200
},
]
}
]
var filterVal = [];
var needle = 100;
for (var i = 0; i < categoryGroups.length; i++) {
var subCategory = categoryGroups[i]['Categories'];
for (var j = 0; j < subCategory.length; j++) {
if (subCategory[j]['Id'] == findId) {
filterVal.push({
catIndex : i,
subCatIndex : j,
id : needle
});
}
}
}
console.log(filterVal);

Here is solution using reduce:
var arr = [{ Id: 1, Categories: [{ Id: 1 }, { Id: 2 }, ] }, { Id: 2, Categories: [{ Id: 100 }, { Id: 200 }, ] } ]
const findPositions = (id) => arr.reduce((r,c,i) => {
let indx = c.Categories.findIndex(({Id}) => Id == id)
return indx >=0 ? {mainIndex: i, categoryIndex: indx} : r
}, {})
console.log(findPositions(100)) // {mainIndex: 1, categoryIndex: 0}
console.log(findPositions(1)) // {mainIndex: 0, categoryIndex: 0}
console.log(findPositions(200)) // {mainIndex: 1, categoryIndex: 1}
console.log(findPositions(0)) // {}

Beside the given answers with fixt depth searh, you could take an recursive approach by checking the Categories property for nested structures.
function getPath(array, target) {
var path;
array.some(({ Id, Categories = [] }) => {
var temp;
if (Id === target) {
path = [Id];
return true;
}
temp = getPath(Categories, target);
if (temp) {
path = [Id, ...temp];
return true;
}
});
return path;
}
var array = [{ Id: 1, Categories: [{ Id: 1 }, { Id: 2 },] }, { Id: 2, Categories: [{ Id: 100 }, { Id: 200 }] }];
console.log(getPath(array, 100));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

problems with for loop inside another for loop Javascript

I have problems in going through these two for loops, I need to get the same elements from the first array within the cycle, but the values ​​are being repeated. I know that they are repeated depending on the data of the second array.
I tried to make comparisons but I could not get the result I want.
var array = [
{
grouper: 1
},
{
grouper: 2
},
{
grouper: 3
},
{
grouper: 4
},
];
var array2 = [
{
value: 1,
grouper: 1,
status: 100
},
{
value: 2,
grouper: 2,
status: 100
},
{
value: 3,
grouper: 3,
status: 100
}
];
for(var i = 0; i<array.length; i++){
for(var j = 0; j<array2.length; j++){
if(array2[j].grouper == array[i].grouper){
console.log(array[i].grouper+'-'+array2[j].value);
}
}
}
This is the result I want, I need all the groupers from the first array and the values from the second array:
1-1
2-2
3-3
4-
The grouper 4, does not have value, but I need to show it.
I need the second array because I'm going to compare with the data from the second array
I do not know if I am doing the process wrong. I hope you can help me.
You could simply track if there was a match (variable shown), and if there were not any, display a "half" line:
var array = [{grouper: 1},{grouper: 2},{grouper: 3},{grouper: 4},];
var array2 = [
{value: 1, grouper: 1, status: 100},
{value: 2, grouper: 2, status: 100},
{value: 3, grouper: 3, status: 100}
];
for(var i = 0; i<array.length; i++){
var shown=false;
for(var j = 0; j<array2.length; j++){
if(array2[j].grouper == array[i].grouper){
console.log(array[i].grouper+'-'+array2[j].value);
shown=true;
}
}
if(!shown){
console.log(array[i].grouper+"-");
}
}
First of all, with the example you provided I believe you want to get back:
1,2,3
There is no 4th object inside of array2, so your conditional (array2[j].grouper == array[i].grouper will never evaluate to true.
The question here is whether you are always comparing the same indexes? In this example, you're comparing array[0] to array2[0] to see if grouper in array equals grouper in array2... that's it????
In that case you just do one loop:
for (var i = 0; i < array.length; i++) {
if (array[i].grouper == array2[i].grouper) {
console.log(array[i].grouper+'-'+array2[j].value);
}
}
#FabianSierra ... with your provided example one just needs to handle the not fulfilled if clause/condition in the most inner loop.
A more generic approach additionally might take into account changing field names (keys). Thus a function and Array.reduce / Array.find based approach provides better code reuse. An example implementation then might look similar to that ...
var array = [{ // in order.
grouper: 1
}, {
grouper: 2
}, {
grouper: 3
}, {
grouper: 4
}];
var array2 = [{ // not in the order similar to `array`.
value: 22,
grouper: 2,
status: 200
}, {
value: 33,
grouper: 3,
status: 300
}, {
value: 11,
grouper: 1,
status: 100
}];
function collectRelatedItemValuesByKeys(collector, item) {
var sourceKey = collector.sourceKey;
var targetKey = collector.targetKey;
var targetList = collector.targetList;
var resultList = collector.result;
var sourceValue = item[sourceKey];
var targetValue;
var relatedItem = targetList.find(function (targetItem) {
return (targetItem[sourceKey] === sourceValue);
});
if (typeof relatedItem !== 'undefined') {
targetValue = relatedItem[targetKey];
} else if (typeof targetValue === 'undefined') {
targetValue = ''; // `relatedItem` does not exist.
}
resultList.push([sourceValue, targetValue].join('-'));
return collector;
}
var resultList = array.reduce(collectRelatedItemValuesByKeys, {
sourceKey: 'grouper',
targetKey: 'value',
targetList: array2,
result: []
}).result;
console.log('resultList : ', resultList);
resultList = array.reduce(collectRelatedItemValuesByKeys, {
sourceKey: 'grouper',
targetKey: 'status',
targetList: array2,
result: []
}).result;
console.log('resultList : ', resultList);
.as-console-wrapper { max-height: 100%!important; top: 0; }

Javascript Fill array with missing object and value

I have an array like bellow each index contains different set of objects,I want to create an uniformal data where object missing in each index will with Value:0 ,
var d = [
[
{axis:"Email",value:59,id:1},
{axis:"Social Networks",value:56,id:2},
],
[
{axis:"Sending Money",value:18,id:6},
{axis:"Other",value:15,id:7},
]
];
how can I get an array like bellow using above above array
var d = [
[
{axis:"Email",value:59,id:1},
{axis:"Social Networks",value:56,id:2},
{axis:"Sending Money",value:0,id:6},
{axis:"Other",value:0,id:7},
],
[
{axis:"Email",value:0,id:1},
{axis:"Social Networks",value:0,id:2},
{axis:"Sending Money",value:18,id:6},
{axis:"Other",value:15,id:7},
]
];
There are two functions:
getAllEntries that find all objects and stores them into a variable accEntries. Then accEntries is used to search for all occurrences in a sub-array of d. This whole process is done in checkArray.
checkArray is used to fetch all found and not-found entries in d. Both Arrays (found and not-found) are then used to build a new sub-array that contains either found entries with certain values and/or not-found entries with values of 0.
Hope this helps:
var d = [
[
{
axis: 'Email',
value: 59,
id: 1
},
{
axis: 'Social Networks',
value: 56,
id: 2
},
],
[
{
axis: 'Sending Money',
value: 18,
id: 6
},
{
axis: 'Other',
value: 15,
id: 7
},
]
];
function getAllEntries(array) {
var uniqueEntries = [];
array.forEach(function (subarray) {
subarray.forEach(function (obj) {
if (uniqueEntries.indexOf(obj) === - 1) uniqueEntries.push(obj);
});
});
return uniqueEntries;
}
function checkArray(array, acceptedEntries) {
var result = [];
array.forEach(function (subArray) {
var subResult = [];
var foundEntries = [];
subArray.forEach(function (obj) {
if (foundEntries.indexOf(obj.axis) === - 1) foundEntries.push(obj.axis);
});
var notFound = acceptedEntries.filter(function (accepted) {
return foundEntries.indexOf(accepted.axis) === - 1;
});
foundEntries.forEach(function (found) {
subArray.forEach(function (obj) {
if (obj.axis === found) subResult.push(obj);
});
});
notFound.forEach(function (notfound, index) {
subResult.push({
axis: notfound.axis,
value: 0,
id: notfound.id
});
});
result.push(subResult);
});
return result;
}
var accEntries = getAllEntries(d);
var result = checkArray(d, accEntries);
console.log(result);
You can loop over the array to find all the unique objects and then again loop over to push the values that are not present comparing with the array of objects of unique keys.
You can use ES6 syntax to find if an object with an attribute is present like uniKeys.findIndex(obj => obj.axis === val.axis); and the to push with a zero value use the spread syntax like d[index].push({...val, value: 0});
Below is the snippet for the implementation
var d = [
[
{axis:"Email",value:59,id:1},
{axis:"Social Networks",value:56,id:2},
],
[
{axis:"Sending Money",value:18,id:6},
{axis:"Other",value:15,id:7},
{axis:"Social Networks",value:89,id:2},
]
];
var uniKeys = [];
$.each(d, function(index, item) {
$.each(item, function(idx, val){
const pos = uniKeys.findIndex(obj => obj.axis === val.axis);
if(pos == - 1) {
uniKeys.push(val);
}
})
})
$.each(d, function(index, item) {
var temp = [];
$.each(uniKeys, function(idx, val){
const pos = item.findIndex(obj => obj.axis === val.axis);
if(pos == - 1) {
d[index].push({...val, value: 0});
}
})
})
console.log(d);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
How about a short shallowCopy function (Object.assign is not available in IE) and otherwise less than 10 new lines of code?
var d = [
[
{axis:"Email",value:59,id:1},
{axis:"Social Networks",value:56,id:2}
],
[
{axis:"Sending Money",value:18,id:6},
{axis:"Other",value:15,id:7}
]
];
var newD_0 = [shallowCopy(d[0][0]), shallowCopy(d[0][1]), shallowCopy(d[1][0]), shallowCopy(d[1][1])];
var newD_1 = [shallowCopy(d[0][0]), shallowCopy(d[0][1]), shallowCopy(d[1][0]), shallowCopy(d[1][1])];
newD_0[2].id = 0;
newD_0[3].id = 0;
newD_1[0].id = 0;
newD_1[1].id = 0;
d = [newD_0, newD_1];
function shallowCopy(obj) {
var copy = {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = obj[key];
}
}
return copy;
}
console.log(JSON.stringify(d));
RESULT:
[
[
{
"axis":"Email",
"value":59,
"id":1
},
{
"axis":"Social Networks",
"value":56,
"id":2
},
{
"axis":"Sending Money",
"value":18,
"id":0
},
{
"axis":"Other",
"value":15,
"id":0
}
],
[
{
"axis":"Email",
"value":59,
"id":0
},
{
"axis":"Social Networks",
"value":56,
"id":0
},
{
"axis":"Sending Money",
"value":18,
"id":6
},
{
"axis":"Other",
"value":15,
"id":7
}
]
]

Check if a key value already exists in a multidimensional array object in angularjs

Suppose I have an array with object like this
array = [
{id:2,cnt:2},{id:3,cnt:3},{id:4,cnt:2},
{id:1,cnt:6},{id:2,cnt:7},{id:5,cnt:4},
{id:2,cnt:4},{id:3,cnt:2},{id:4,cnt:2},
{id:3,cnt:2},{id:4,cnt:3},{id:5,cnt:2}
];
where I need to create another array with the object where I need to add cnt value with id.
Output suppose to be like this.
output = [
{id:1,cnt:6},{id:2,cnt:13},{id:3,cnt:7},{id:4,cnt:7},{id:5,cnt:6}
];
what I have tried so far is
var general = [];
angular.forEach(array, function(value){
angular.forEach(value, function(val,key){
angular.forEach(general, function(val1,key1){
if(val1.id === val.id){
val1.cnt +=val.cnt
//#TOD0 how to add value of count and put it on general
}else{
//#TODO
general.push(val);
}
});
});
});
console.log(general);
I am unable to achieve my output. I have marked as TODO where I am confused. Can someone help me? Thanks in advance.
Array.reduce can help you a lot - you basically create a new array, and iterate your current array and check the new array to see if the current item exists. If it does, add the cnt - else add the whole item:
var mashed = arr.reduce(function(m, cur, idx) {
var found = false;
for (var i =0; i < m.length; i++) {
if (m[i].id == cur.id) {
m[i].cnt += cur.cnt;
found = true;
}
}
if (!found) {
m.push(cur)
}
return m;
}, [])
Fiddle demo: https://jsfiddle.net/1ffqv9g0/
var arr = [
{id:2,count:2,color:"red"},{id:3,count:3,color:"black"},{id:4,count:2,color:"white"},
{id:1,count:6,color:"green"},{id:2,count:7,color:"red"},{id:5,count:4,color:"blue"},
{id:2,count:4,color:"red"},{id:3,count:2,color:"black"},{id:4,count:2,color:"white"},
{id:3,count:2,color:"black"},{id:4,count:3,color:"red"},{id:5,count:2,color:"blue"}
];
var obj={};
arr.forEach(function(a){
obj[a.id]=obj[a.id]||[0];
obj[a.id][0]=obj[a.id][0]+a["count"];
obj[a.id][1]=a.color;
})
//console.log(obj);
var brr=Object.keys(obj).map(function(a){
return {"id":a,"count":obj[a][0],"color":obj[a][1]};
})
console.log(brr);
You could use a hash table for the result. For an ordered result, you could sort the result.
var array = [{ id: 2, cnt: 2 }, { id: 3, cnt: 3 }, { id: 4, cnt: 2 }, { id: 1, cnt: 6 }, { id: 2, cnt: 7 }, { id: 5, cnt: 4 }, { id: 2, cnt: 4 }, { id: 3, cnt: 2 }, { id: 4, cnt: 2 }, { id: 3, cnt: 2 }, { id: 4, cnt: 3 }, { id: 5, cnt: 2 }],
grouped = [];
array.forEach(function (a) {
if (!this[a.id]) {
this[a.id] = { id: a.id, cnt: 0 };
grouped.push(this[a.id]);
}
this[a.id].cnt += a.cnt;
}, Object.create(null));
grouped.sort(function (a, b) { return a.id - b.id; });
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Get all possible options for a matrix in javascript

I have an 'item' object in JavaScript, and the item can have settings like
color, size, etc.
I need to get all possible combinations in an array.
So lets say we have an item that looks like this:
var newItem = {
name: 'new item',
Settings: [
{name: 'color', values: ['green', 'blue', 'red']},
{name: 'size', values: ['15', '18', '22']},
{name: 'gender',values: ['male', 'female']}
]
};
I need to somehow get this:
[
[{SettingName:'color',value:'green'},{SettingName:'size',value:'15'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'blue'},{SettingName:'size',value:'15'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'red'},{SettingName:'size',value:'15'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'green'},{SettingName:'size',value:'18'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'blue'},{SettingName:'size',value:'18'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'red'},{SettingName:'size',value:'18'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'green'},{SettingName:'size',value:'22'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'blue'},{SettingName:'size',value:'22'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'red'},{SettingName:'size',value:'22'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'green'},{SettingName:'size',value:'15'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'blue'},{SettingName:'size',value:'15'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'red'},{SettingName:'size',value:'15'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'green'},{SettingName:'size',value:'18'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'blue'},{SettingName:'size',value:'18'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'red'},{SettingName:'size',value:'18'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'green'},{SettingName:'size',value:'22'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'blue'},{SettingName:'size',value:'22'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'red'},{SettingName:'size',value:'22'},{SettingName:'gender',value:'female'}]
]
This can be a good interview question.
See JS Bin for running example.
getAllPermutations(newItem);
function getAllPermutations(item) {
var permutations = [];
getAllPermutations0(item, permutations, []);
console.log(permutations);
}
function getAllPermutations0(item, permutations, array) {
if (array && array.length === item.Settings.length) {
permutations.push(array.slice()); // The slice clone the array
return;
}
var index = array.length;
var setting = item.Settings[index];
for (var i = 0; i < setting.values.length; i++) {
if (index === 0)
array = [];
var currValue = setting.values[i];
array.push({
SettingName: setting.name,
value: currValue
});
getAllPermutations0(item, permutations, array);
array.pop(); // pop the old one first
}
}
Here is a none recursive solution. It takes an empty or existing settings "matrix" and a values array, and return a new matrix as a combination of existing matrix content cloned for each new value, appended with pairs of new value setting items.
[A] -> [1,2] gives [A][1][A][2]
[A][1][A][2] -> [X,Y] gives [A][1][X][A][2][Y][A][2][X][A][1][Y]
and so on
function processSettings(settings, name, values) {
if (settings.length == 0) {
values.forEach(function(value) {
settings.push( [{ SettingName: name, value: value }] )
})
} else {
var oldSettings = JSON.parse(JSON.stringify(settings)), settings = [], temp, i = 0
for (i; i<values.length; i++) {
temp = JSON.parse(JSON.stringify(oldSettings))
temp.forEach(function(setting) {
setting.push( { SettingName: name, value: values[i] } )
settings.push(setting)
})
}
}
return settings
}
You can now create the desired settings literal this way :
var settings = []
for (var i=0; i<newItem.Settings.length; i++) {
var item = newItem.Settings[i]
settings = processSettings(settings, item.name, item.values)
}
demo -> http://jsfiddle.net/b4ck98mf/
The above produces this :
[
[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"female"}]
]
You can use Array.prototype.map(), for loop, while loop, Array.prototype.concat(). Iterate gender values; select each of color, size value in succession beginning at index 0 of either; iterating the furthest adjacent array from current gender, increment the index of the closest adjacent array; merge the resulting two gender arrays to form a single array containing all combinations of gender, color, size
var colors = newItem.Settings[0].values;
var sizes = newItem.Settings[1].values;
var gen = newItem.Settings[2].values;
var i = sizes.length;
var res = [].concat.apply([], gen.map(function(value, key) {
var next = -1;
var arr = [];
for (var curr = 0; curr < i; curr++) {
while (next < i - 1) {
arr.push([{
SettingName: "gender",
value: value
}, {
SettingName: "size",
value: sizes[curr]
}, {
SettingName: "color",
value: colors[++next]
}])
}
next = -1;
}
return arr
}))
var newItem = {
"name": "new item",
"Settings": [{
"name": "color",
"values": [
"green",
"blue",
"red"
]
}, {
"name": "size",
"values": [
"15",
"18",
"22"
]
}, {
"name": "gender",
"values": [
"male",
"female"
]
}]
}
var colors = newItem.Settings[0].values;
var sizes = newItem.Settings[1].values;
var gen = newItem.Settings[2].values;
var i = sizes.length;
var res = [].concat.apply([], gen.map(function(value, key) {
var next = -1;
var arr = [];
for (var curr = 0; curr < i; curr++) {
while (next < i - 1) {
arr.push([{
SettingName: "gender",
value: value
}, {
SettingName: "size",
value: sizes[curr]
}, {
SettingName: "color",
value: colors[++next]
}])
}
next = -1;
}
return arr
}))
document.querySelector("pre").textContent = JSON.stringify(res, null, 2)
<pre></pre>
plnkr http://plnkr.co/edit/C2fOJpfwOrlBwHLQ2izh?p=preview
An approach using Array.prototype.reduce(), Array.prototype.sort(), Object.keys(), for loop, while loop
var newItem = {
name: 'new item',
Settings: [
{
name: 'color',
values: ['green', 'blue', 'red']
},
{
name: 'size',
values: ['15', '18', '22']
},
{
name: 'gender',
values: ['male', 'female']
}
]
};
var props = ["SettingName", "value"];
var settings = newItem.Settings;
function p(settings, props) {
var data = settings.reduce(function(res, setting, index) {
var name = setting.name;
var obj = {};
obj[name] = setting.values;
res.push(obj);
return res.length < index ? res : res.sort(function(a, b) {
return a[Object.keys(a)[0]].length - b[Object.keys(b)[0]].length
})
}, []);
var key = data.splice(0, 1)[0];
return [].concat.apply([], key[Object.keys(key)].map(function(value, index) {
return data.reduce(function(v, k) {
var keys = [v, k].map(function(obj) {
return Object.keys(obj)[0]
});
var i = Math.max.apply(Math, [v[keys[0]].length, k[keys[1]].length]);
var next = -1;
var arr = [];
for (var curr = 0; curr < i; curr++) {
while (next < i - 1) {
var a = {};
a[props[0]] = keys[0];
a[props[1]] = v[keys[0]][++next];
var b = {};
b[props[0]] = keys[1];
b[props[1]] = k[keys[1]][next];
var c = {};
c[props[0]] = Object.keys(key)[0];
c[props[1]] = value;
arr.push([a, b, c]);
};
next = -1;
}
return arr
});
}));
}
document.querySelector("pre").textContent = JSON.stringify(
p(settings, props), null, 2
);
<pre></pre>

Build JSON Object from string containing multi-dimensional

I have an array of name/value objects (below). The names are formatted to represent multi-dimensional array.
I need to build a full JavaScript object out of it(bottom).
[{
name: "getQuote[origin]",
value: "Omaha,NE"
},
{
name: "getQuote[destination]",
value: "10005"
},
{
name: "getQuote[country]",
value: "us"
},
{
name: "getQuote[vehicles][0][year]",
value: "1989"
},
{
name: "getQuote[vehicles][0][make]",
value: "Daihatsu"
},
{
name: "getQuote[vehicles][0][model]",
value: "Charade"
},
{
name: "getQuote[vehicles][0][count]",
value: "1"
}]
Into something like this:
{getQuote :
{ origin : Omaha},
{ destination : 10005},
{vehicles : [
{
year : 1989,
make: Honda,
model : accord
},
{
//etc
}]
n
You can do it manually, like this:
var source = [ /* Your source array here */ ];
var dest = {};
for(var i = 0; i < source.length; i++)
{
var value = source[i].value;
var path = source[i].name.split(/[\[\]]+/);
var curItem = dest;
for(var j = 0; j < path.length - 2; j++)
{
if(!(path[j] in curItem))
{
curItem[path[j]] = {};
}
curItem = curItem[path[j]];
}
curItem[path[j]] = value;
}
dest is the resulting object.
Check it working here: http://jsfiddle.net/pnkDk/7/

Categories

Resources