Related
I am stuck to solve this problem.
Convert an array below
var input = [
'animal/mammal/dog',
'animal/mammal/cat/tiger',
'animal/mammal/cat/lion',
'animal/mammal/elephant',
'animal/reptile',
'plant/sunflower'
]
to json Object
var expectedResult = {
"animal": {
"mammal": {
"dog": true,
"cat": {
"tiger": true,
"lion": true
},
"elephant": true
},
"reptile": true
},
"plant": {
"sunflower": true
}
}
Which data structure and algorithm can I apply for it?
Thanks
You need to first split each element to convert to array
using reverse reduce method you can convert them to object.
And your last step is merge this objects.
Lodash.js merge method is an one way to merge them.
var input = ['animal/mammal/dog','animal/mammal/cat/tiger','animal/mammal/cat/lion', 'animal/mammal/elephant','animal/reptile', 'plant/sunflower']
var finalbyLodash={}
input.forEach(x=>{
const keys = x.split("/");
const result = keys.reverse().reduce((res, key) => ({[key]: res}), true);
finalbyLodash = _.merge({}, finalbyLodash, result);
});
console.log(finalbyLodash);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>
To make the process more understandable, break the problem down into pieces.
The first step is convert each string into something we can use, converting this:
"animal/mammal/dog"
into this:
[ "animal", "mammal", "dog" ]
That's an array of property names needed to build the final object.
Two functions will accomplish this for you, String.prototype.split() to split the string into an array, and Array.prototype.map() to transform each of the array elements:
let splitIntoNames = input.map(str => str.split('/'));
The intermediate result is this:
[
[ "animal", "mammal", "dog" ],
[ "animal", "mammal", "cat", "tiger" ],
[ "animal", "mammal", "cat", "lion" ],
[ "animal", "mammal", "elephant" ],
[ "animal", "reptile" ],
[ "plant", "sunflower" ]
]
Next step is to iterate over each array, using Array.prototype.forEach() to add properties to the object. You could add properties to the object with a for loop, but let's do that with a recursive function addName():
function addName(element, list, index) {
if (index >= list.length) {
return;
}
let name = list[index];
let isEndOfList = index === list.length - 1;
element[name] = element[name] || (isEndOfList ? true : {});
addName(element[name], list, index + 1);
}
let result = {};
splitIntoNames.forEach((list) => {
addName(result, list, 0);
});
The result:
result: {
"animal": {
"mammal": {
"dog": true,
"cat": {
"tiger": true,
"lion": true
},
"elephant": true
},
"reptile": true
},
"plant": {
"sunflower": true
}
}
const input = [
"animal/mammal/dog",
"animal/mammal/cat/tiger",
"animal/mammal/cat/lion",
"animal/mammal/elephant",
"animal/reptile",
"plant/sunflower",
];
let splitIntoNames = input.map((str) => str.split("/"));
console.log("splitIntoNames:", JSON.stringify(splitIntoNames, null, 2));
function addName(element, list, index) {
if (index >= list.length) {
return;
}
let name = list[index];
let isEndOfList = index === list.length - 1;
element[name] = element[name] || (isEndOfList ? true : {});
addName(element[name], list, index + 1);
}
let result = {};
splitIntoNames.forEach((list) => {
addName(result, list, 0);
});
console.log("result:", JSON.stringify(result, null, 2));
You can create a function that will slice every element from the array by "/" than you put the results into a variable and than just mount the Json. I mean something like that below:
window.onload = function() {
var expectedResult;
var input = [
'animal/mammal/dog',
'animal/mammal/cat/tiger',
'animal/mammal/cat/lion',
'animal/mammal/elephant',
'animal/reptile',
'plant/sunflower'
]
input.forEach(element => {
var data = element.split('/');
var dog = data[2] === 'dog' ? true : false
var tiger = data[2] === 'cat' && data[3] === 'tiger' ? true : false
var lion = data[2] === 'cat' && data[3] === 'lion' ? true : false
expectedResult = {
data[0]: {
data[1]: {
"dog": dog,
"cat": {
"tiger": tiger,
"lion": lion
}
}
}
}
})
}
Late to the party, here is my try. I'm implmenting recursive approach:
var input = ['animal/mammal/dog', 'animal/mammal/cat/tiger', 'animal/mammal/cat/lion', 'animal/mammal/elephant', 'animal/reptile', 'plant/sunflower'];
result = (buildObj = (array, Obj = {}) => {
array.forEach((val) => {
keys = val.split('/');
(nestedFn = (object) => {
outKey = keys.shift();
object[outKey] = object[outKey] || {};
if (keys.length == 0) object[outKey] = true;
if (keys.length > 0) nestedFn(object[outKey]);
})(Obj)
})
return Obj;
})(input);
console.log(result);
I try with array reduce, hope it help
let input = [
"animal/mammal/dog",
"animal/mammal/cat/tiger",
"animal/mammal/cat/lion",
"animal/elephant",
"animal/reptile",
"plant/sunflower",
];
let convertInput = (i = []) =>
i.reduce((prev, currItem = "") => {
let pointer = prev;
currItem.split("/").reduce((prevPre, currPre, preIdx, arrPre) => {
if (!pointer[currPre]) {
pointer[currPre] = preIdx === arrPre.length - 1 ? true : {};
}
pointer = pointer[currPre];
}, {});
return prev;
}, {});
console.log(JSON.stringify(convertInput(input), null, 4));
I am trying to group items an array of items by a property and then reindex the result starting from 0.
The following function returns a grouped set of items.
groupItemBy(array, property) {
let hash = {},
props = property.split('.');
for (let i = 0; i < array.length; i++) {
let key = props.reduce( (acc, prop) => {
return acc && acc[prop];
}, array[i]);
if (!hash[key]) hash[key] = [];
hash[key].push(array[i]);
}
return hash;
}
The result is an array of arrays, and something like:
[{
"1193312":[
{
"description":"Item 1",
"number": "1193312"
}
],
"1193314":[
{
"itemDesc":"Item 2"},
"number": "1193314"
{
"description":"Item 3",
"number": "1193314"
}
],
etc...
}]
From here I'd like to map 1193312 to 0, and 1193314 to 1, etc.
I tried .filter(val => val) on the result, but that seemed to have no effect.
You need to use an intermediate key replacement:
function groupItemBy(array, property) {
let hash = {}
let props = property.split('.')
let keys = []
for (let i = 0; i < array.length; i++) {
let key = props.reduce((acc, prop) => {
return acc && acc[prop];
}, array[i]);
let subst = keys.indexOf(key)
if (subst === -1) {
keys.push(key)
subst = keys.length - 1
}
if (!hash[subst]) hash[subst] = [];
hash[subst].push(array[i]);
}
return hash;
}
[ https://jsfiddle.net/05t9141p/ ]
You could use map for the array part, and Object.values and reduce for the renumber part.
const data = [{
"1193312":[
{
"time":"2018-02-20",
"description":"Item 1",
"number": "1193312"
}
],
"1193314":[
{
"time":"2018-02-21",
"itemDesc":"Item 2",
"number": "1193314"
},{
"time":"2018-02-21",
"description":"Item 3",
"number": "1193314"
}
]
}];
const renumbered =
data.map((m) => Object.values(m).reduce((a,v,ix) => (a[ix] = v, a), {}));
console.log(renumbered);
var data = [{
"1193312":[
{
"description":"Item 1",
"number": "1193312"
}
],
"1193314":[
{
"itemDesc":"Item 2",
"number": "1193314"},
{
"description":"Item 3",
"number": "1193314"
}
]
}]
var newData = Object.keys(data[0]).map(function(key,index){
var newObj={};
newObj[index] = data[0][key];
return newObj;
});
console.log(newData);
If you can use ES6:
var arr = [{
"1193312":[
{
"time":"2018-02-20",
"description":"Item 1"
}
],
"1193314":[
{
"time":"2018-02-21",
"itemDesc":"Item 2"},
{
"time":"2018-02-21",
"description":"Item 3"
}
]
}];
var data = arr[0];
var res = Object.entries(data).map(([key, value]) => ({[key]: value}));
console.log(res);
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
}
]
]
I see many topics on this site, but every one deal with single Array.
My need is to convert every object with number as key to array.
For exemple,
I have an object like :
{
"parent":{
"0":{
"child":false
},
"1":{
"child":false
},
"4": {
"child":false
}
}
}
And i would like
{
"parent": [
{
"child":false
},
{
"child":false
},
null,
null,
{
"child":false
}
]
}
This is an exemple, my object can be really deep and content many object like this, so i need a generic function.
UPDATE
My try sor far using code of #Nenad Vracar :
function recursiveIteration(object) {
var newob = {};
for (var property in object) {
if (object.hasOwnProperty(property)) {
if (typeof object[property] == "object"){
var result = {};
var keys = Object.keys(object[property]);
if ($.isNumeric(keys[0])) {
console.log("======> "+property+" is table");
for (var i = 0; i <= keys[keys.length - 1]; i++) {
if (keys.indexOf(i.toString()) != -1) {
result[property] = (result[property] || []).concat(object[property][i]);
} else {
result[property] = (result[property] || []).concat(null);
}
}
newob[property] = result;
recursiveIteration(object[property]);
}
newob[property] = object[property];
recursiveIteration(object[property]);
}else{
newob[property] = object[property];
}
}
}
return newob;
}
And the JSFiddle for live try
Thanks you guys !
I think this is what you want:
var data = {
"parent": {
"0": {
"child": false
},
"1": {
"child": false
},
"4": {
"child": false
}
}
};
var convert = function(data) {
// not an object, return value
if (data === null || typeof data !== 'object')
return data;
var indices = Object.keys(data);
// convert children
for (var i = 0; i < indices.length; i++)
data[indices[i]] = convert(data[indices[i]]);
// check if all indices are integers
var isArray = true;
for (var i = 0; i < indices.length; i++) {
if (Math.floor(indices[i]) != indices[i] || !$.isNumeric(indices[i])) {
isArray = false;
break;
}
}
// all are not integers
if (!isArray) {
return data;
}
// all are integers, convert to array
else {
var arr = [];
for (var i = 0, n = Math.max.apply(null, indices); i <= n; i++) {
if (indices.indexOf(i.toString()) === -1)
arr.push(null);
else
arr.push(data[i]);
}
return arr;
}
};
console.log( convert(data) );
Here is a working jsfiddle with the data you provided in the update.
You can do this with Object.keys() and one for loop
var data = {"parent":{"0":{"child":false},"1":{"child":false},"4":{"child":false}}}, result = {}
var keys = Object.keys(data.parent);
for (var i = 0; i <= keys[keys.length - 1]; i++) {
if (keys.indexOf(i.toString()) != -1) {
result.parent = (result.parent || []).concat(data.parent[i]);
} else {
result.parent = (result.parent || []).concat(null);
}
}
console.log(result)
You might achieve this job with a very simple recursive Object method as follows. Any valid nested object (including arrays) within an object structure will be converted into an array, in which the properties are replaced with indices and values are replaced by items.
Object.prototype.valueToItem = function(){
return Object.keys(this).map(e => typeof this[e] === "object" &&
this[e] !== null &&
!Array.isArray(this[e]) ? this[e].valueToItem()
: this[e]);
};
var o = { name: "terrible",
lastname: "godenhorn",
cars: ["red barchetta", "blue stingray"],
age: 52,
child: { name: "horrible",
lastname: "godenhorn",
cars: ["fiat 124", "tata"],
age: 24,
child:{ name: "badluck",
lastname: "godenhorn",
cars: ["lamborghini countach"],
age: 2,
child: null}}},
a = o.valueToItem();
console.log(a);
Ok modified to the OP's conditions but still generic as much as it can be.
Object.prototype.valueToItem = function(){
var keys = Object.keys(this);
return keys.reduce((p,c) => typeof this[c] === "object" &&
this[c] !== null &&
!Array.isArray(this[c]) ? keys.every(k => Number.isInteger(k*1)) ? (p[c] = this[c].valueToItem(),p)
: this[c].valueToItem()
: this
,new Array(~~Math.max(...keys)).fill(null));
};
var o = {
parent: {
0: {
child : false
},
1: {
child : false
},
4: {
child : {
0: {
child : false
},
3: {
child : false
},
5: {
child : false
}
}
}
}
};
a = o.valueToItem();
console.log(JSON.stringify(a,null,4));
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>