I am stuck at this, where I want to set a combination for the variant object.
the variants data is:
"Variants": [
{
"name": "color",
"variants": [
{
"id": "e637bd15-d5e3-486b-aba3-3193cfb621bd",
"variantName": "red"
},
{
"id": "ee81a10d-5cdb-4e99-bc54-9f729025ff6b",
"variantName": "yellow"
}
],
"id": 1
},
{
"name": "size",
"variants": [
{
"id": "7546d9dd-410e-4bd7-99f2-cea7b5fd558b",
"variantName": "large"
},
{
"id": "e787b3c5-45db-4502-ab1b-dfe1670814fc",
"variantName": "small"
}
],
"id": 2
}
],
I want the console to print:
red/large, red/small, yellow/large, yellow/small.
but instead I get:
the code I wrote is:
const combinations = () => {
let result = [];
let len = data.length;
let i, j;
for (i = 0; i < len; i++) {
let len2 = data[i].variants.length;
for (j = 0; j < len2 - 1; j++) {
result.push(
data[j].variants[i].variantName +
'/' +
data[i].variants[j + 1].variantName
);
}
}
return console.log(result);
};
where did I go wrong? what I am missing, thx in advance.
you can achieve this using flatMap and map.
let data =[{name:"color",variants:[{id:"e637bd15-d5e3-486b-aba3-3193cfb621bd",variantName:"red"},{id:"ee81a10d-5cdb-4e99-bc54-9f729025ff6b",variantName:"yellow"}],id:1},{name:"size",variants:[{id:"7546d9dd-410e-4bd7-99f2-cea7b5fd558b",variantName:"large"},{id:"e787b3c5-45db-4502-ab1b-dfe1670814fc",variantName:"small"}],id:2}]
let a = data[0].variants.flatMap((color) => {
return data[1].variants.map((size) => `${color.variantName}/${size.variantName}`)
})
console.log(a)
If you want the cartesian product when the number of arrays is not explicitly specified can do something like this
reference
let data = [
{
"name": "color",
"variants": [
{
"id": "e637bd15-d5e3-486b-aba3-3193cfb621bd",
"variantName": "red"
},
{
"id": "ee81a10d-5cdb-4e99-bc54-9f729025ff6b",
"variantName": "yellow"
}
],
"id": 1
},
{
"name": "size",
"variants": [
{
"id": "7546d9dd-410e-4bd7-99f2-cea7b5fd558b",
"variantName": "large"
},
{
"id": "e787b3c5-45db-4502-ab1b-dfe1670814fc",
"variantName": "small"
},
{
"id": "e787b3c5-45dssb-4502-ab1b-dfe1670814fc",
"variantName": "medium"
}
],
"id": 2
},
{
"name": "weight",
"variants": [
{
"id": "7546d9dd-410e-4bd7-99f2-cea7b5fd558b",
"variantName": "heavy"
},
{
"id": "e787b3c5-45db-4502-ab1b-dfe1670814fc",
"variantName": "light"
}
],
"id": 3
},
{
"name": "material",
"variants": [
{
"id": "7546d9dd-410e-4bdhjh2-cea7b5fd558b",
"variantName": "plastic"
},
{
"id": "e787b3c5-45db-kkhkab1b-dfe1670814fc",
"variantName": "wood"
},
{
"id": "e787b3c5-45dbhhab1b-dfe1670814fc",
"variantName": "cement"
},
],
"id": 4
}
]
let combined = data.reduce((a,{variants})=>{
return a.flatMap(x=>variants.map(y=>x.concat(y.variantName)))
},[[]]).map((z) => z.join("/"))
console.log(combined)
Related
I have a nested array like below. There are about 100 de objects in the array. The de objects also have deg[0] array but most likely I will only have the first index. Now the trick is that the de are subset of deg. Which means each deg can have say 10 de. How can I retrieve the deg and there associated de and map it into a new array like:
newArray = [
deg1: [
{de1},
{de2}
],
deg2: [
{de1},
{de2}
]
]
Here is my nested array. I posted four but the list is over a 100.
{
"name": "Report",
"id": "2YYUEZ6I1r9",
"dse1": [
{
"de1": {
"name": "Number",
"id": "HjMOngg3kuy",
"de1-av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg1": [
{
"name": "TB",
"id": "2XJB1JO9qX8"
}
]
}
},
{
"de2": {
"name": "Number of",
"id": "a3dtGETTawy",
"de2-av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg1": [
{
"name": "Secondary",
"id": "w99RWzXHgtw"
}
]
}
},
{
"de1": {
"name": "Number of",
"id": "a3dtGETTawy",
"de1av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg2": [
{
"name": "Secondary",
"id": "w99RWzXHgtw"
}
]
}
},
{
"de2": {
"name": "Number of",
"id": "a3dtGETTawy",
"de2av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg2": [
{
"name": "Tertiary",
"id": "w99RWzXHgtw"
}
]
}
}
]
}
Group array of objects by property (this time a property to be matched by a reg exp) using Array.reduce.
Update: Ignoring missing keys.
var input={name:"Report",id:"2YYUEZ6I1r9",dse1:[{de1:{name:"Number",id:"HjMOngg3kuy","de1-av":[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg1:[{name:"TB",id:"2XJB1JO9qX8"}]}},{de2:{name:"Number of",id:"a3dtGETTawy","de2-av":[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg1:[{name:"Secondary",id:"w99RWzXHgtw"}]}},{de1:{name:"Number of",id:"a3dtGETTawy",de1av:[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg2:[{name:"Secondary",id:"w99RWzXHgtw"}]}},{de2:{name:"Number of",id:"a3dtGETTawy",de2av:[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg2:[{name:"Tertiary",id:"w99RWzXHgtw"}]}}]}
var reg = new RegExp("^de[0-9]+$");
var reg2 = new RegExp("^deg[0-9]+$");
let obj = input['dse1'].reduce(function(agg, item) {
// do your group by logic below this line
var key = Object.keys(item).find(function(key) {
return key.match(reg) ? key : null;
})
if (key) {
var key2 = Object.keys(item[key]).find(function(key) {
return key.match(reg2) ? key : null;
})
agg[key] = agg[key] || [];
if (key2) {
var to_push = {}
to_push[key2] = item[key][key2]
agg[key].push(to_push)
}
}
// do your group by logic above this line
return agg
}, {});
console.log(obj)
.as-console-wrapper {
max-height: 100% !important;
}
I have an array of widgets containing multiple objects. Each object contains an array called cards which contains just a single object. I need help with extracting all the cards object and making a new cards array containing all the cards as elements
{
"widgets" : [
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
}
]
},
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
}
]
}
]
}
How I want is
{
"widgets": [
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
},
{
"data": {},
"layout": 1
}
]
}
]
}
You can loop over the original object orig and extract it's cards into a new array allCards:
const allCards = [];
for (let widget of orig.widgets) {
allCards.push(widget.cards[0]);
}
Then you can construct a new object with these extracted cards.
Given your requirement, the below might work.
let x = {
"widgets" : [
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
}
]
},
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
}
]
}
]
}
let y = {"widgets": [{...x.widgets[0], "cards":[]}]};
x.widgets.forEach(el => y.widgets[0].cards.push(...[].concat(el.cards)));
You can try this code that taek into account the type of each widget :
object = {
"widgets" : [
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
}
]
},
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
}
]
},
{
"type": "Table",
"cards": [
{
"data": {},
"layout": 1
}
]
},
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
}
]
}
]
}
new_object = {"widgets" : []}
for (let i=0; i < object["widgets"].length; i++) {
exist = false
for (let j=0; j < new_object["widgets"].length; j++) {
if (new_object["widgets"][j]["type"] === object["widgets"][i]["type"]){
exist = true
new_object["widgets"][j]["cards"].push(object["widgets"][i]["cards"][0])
}
}
if (exist === false){
new_object["widgets"].push(object["widgets"][i])
}
}
console.log(new_object)
I have this object below
{
"root": {
"data": {
"page": 1,
"contents": [
{
"node": {
"id": "UzpfSTE",
"stats": {
"viewers": {
"nodes": [
{
"id": "1",
"name": "John"
},
{
"id": "2",
"name": "Shaun"
}
]
}
}
}
},
{
"node": {
"id": "UzpfSTG",
"stats": {
"viewers": {
"nodes": [
{
"id": "3",
"name": "Liam"
}
]
}
}
}
}
]
}
}
}
There is contents node, each of them will have many viewers, all I want is to extract all viewers name to an array, in this instance my result will be [John, Shaun, Liam]
I have this approach:
const data = JSON.parse(rt)
const contents = data.root.data.contents
const newArray = []
for (i = 0; i < contents.length; i++) {
arr2 = contents[i].node.stats.viewers.nodes
for (n = 0; n < arr2.length; n++) {
name = arr2[n].name
newArray.push(name)
}
}
console.log(newArray)
>>> [John, Shaun, Liam]
Which does the job, but occasionaly the object key names change and I have to alter everytime.
So is there more elegant way to do this?
You can simplify that imperative logic like this.
I don't understand what you mean by "the object key names change" though
const data = {
"root": {
"data": {
"page": 1,
"contents": [{
"node": {
"id": "UzpfSTE",
"stats": {
"viewers": {
"nodes": [{
"id": "1",
"name": "John"
},
{
"id": "2",
"name": "Shaun"
}
]
}
}
}
},
{
"node": {
"id": "UzpfSTG",
"stats": {
"viewers": {
"nodes": [{
"id": "3",
"name": "Liam"
}]
}
}
}
}
]
}
}
}
const names = data.root.data.contents.flatMap(({
node: {
stats: {
viewers: {
nodes
}
}
}
}) => nodes.map(({
name
}) => name))
console.log(names)
const data = JSON.parse(rt)
const contents = data.root.data.contents
const viewers = contents.map(item => item.node.stats.viewers.nodes).flat()
const viewerNames = viewers.map(viewer => viewer.name)
I'm stuck once more with adding properties to a deeply nested array. What I do have is:
myArray = [
{
"id": "123",
"station": {
"id": 5,
"name": "Teststation"
},
"values": [
{
"id": "way",
"values": [ 339, 340, 341 ]
},
{
"id": "time",
"values": [ 1, 2, 3 ]
},
{
"name": "element_1",
"type": "line",
"result": "nok"
},
{
"name": "element_2",
"type": "rect",
"result": "nok"
},
{
"name": "element_3",
"type": "line",
"result": "ok"
}
]
}
]
myArray might contain more objects which would have the same structure like this one. So I have to loop them. What I want to achieve is:
I want to add properties to the object which own a propertiy called "line" or "rect" and the new property depends on the value of result
So the new outcome should look like:
myArray = [
{
"id": "123",
"station": {
"id": 5,
"name": "Teststation"
},
"values": [
{
"id": "way",
"values": [ 339, 340, 341 ]
},
{
"id": "time",
"values": [ 1, 2, 3 ]
},
{
"name": "element_1",
"type": "line",
"result": "nok"
"line": { color: 'red' }
},
{
"name": "element_2",
"type": "rect",
"result": "nok",
"opacity": 0.2,
"line": { color: 'gray', width: 0 },
"fillcolor": 'green'
},
{
"name": "element_3",
"type": "line",
"result": "ok"
"line": { color: 'green' }
}
]
}
]
What I tried so far seemed to work until I realized: It returns an array with an array with that object. I don't understand why it is doing so and how to get only an array with the object. Can anyone help me out on that?
addColor(myArray) {
return myArray.map(obj => {
for (const prop in obj) {
if (obj.hasOwnProperty(prop) && Array.isArray(obj[prop])) {
for (const item in obj[prop]) {
if (obj[prop][item].hasOwnProperty('result') && (obj[prop][item].type === 'line')) {
obj[prop][item].result === 'nok' ? obj[prop][item].line = { color: 'red' } : obj[prop][item].line = { color: 'green' };
} else if (obj[prop][item].hasOwnProperty('result') && (obj[prop][item].type === 'rect')) {
obj[prop][item].opacity = 0.2;
obj[prop][item].line = { color: 'gray', width: 0 };
obj[prop][item].result === 'nok' ? (obj[prop][item].fillcolor = 'red') : (obj[prop][item].fillcolor = 'green');
}
}
}
}
console.log('myArray out', myArray);
// It doesn't return anything so far so I added
return myArray
// But then I do get [[{}]]
});
}
Adding working snippet, with a small change in your code:
var myArray = [
{
"id": "123",
"station": {
"id": 5,
"name": "Teststation"
},
"values": [
{
"id": "way",
"values": [ 339, 340, 341 ]
},
{
"id": "time",
"values": [ 1, 2, 3 ]
},
{
"name": "element_1",
"type": "line",
"result": "nok"
},
{
"name": "element_2",
"type": "rect",
"result": "nok"
},
{
"name": "element_3",
"type": "line",
"result": "ok"
}
]
}
];
function addColor(myArray) {
const x = myArray.map(obj => {
for (const prop in obj) {
if (obj.hasOwnProperty(prop) && Array.isArray(obj[prop])) {
for (const item in obj[prop]) {
if (obj[prop][item].hasOwnProperty('result') && (obj[prop][item].type === 'line')) {
obj[prop][item].result === 'nok' ? obj[prop][item].line = { color: 'red' } : obj[prop][item].line = { color: 'green' };
} else if (obj[prop][item].hasOwnProperty('result') && (obj[prop][item].type === 'rect')) {
obj[prop][item].opacity = 0.2;
obj[prop][item].line = { color: 'gray', width: 0 };
obj[prop][item].result === 'nok' ? (obj[prop][item].fillcolor = 'red') : (obj[prop][item].fillcolor = 'green');
}
}
}
}
return obj; //<---- Check here
});
return x;
}
addColor(myArray);
const myArray = [{
"id": "123",
"station": {
"id": 5,
"name": "Teststation"
},
"values": [{
"id": "way",
"values": [339, 340, 341]
},
{
"id": "time",
"values": [1, 2, 3]
},
{
"name": "element_1",
"type": "line",
"result": "nok"
},
{
"name": "element_2",
"type": "rect",
"result": "nok"
},
{
"name": "element_3",
"type": "line",
"result": "ok"
}
]
}]
const modifiedArray = myArray.map(item => {
const newItem = Object.assign({}, item);
if (newItem.values) {
const newItemValues = newItem.values.map(value => {
const additionalProps = {};
if (value.type === 'line') {
additionalProps.line = {
color: (value.result === 'ok' && 'green') || 'red'
};
}
if (value.type === 'rect') {
additionalProps.opacity = 0.2;
additionalProps.line = {
color: 'gray',
width: 0
};
additionalProps.fillcolor = (value.result === 'ok' && 'green') || 'red';
}
const newValue = Object.assign({}, value, additionalProps);
return newValue;
});
newItem.values = newItemValues;
}
return newItem;
});
console.log('original:', myArray);
console.log('modified:', modifiedArray);
I'm trying to transform this JSON into array so that I can simply list them as key-value pairs in html. The JSON has nested properties which I want to retain but I want to stringify only those objects that contain "units" and "value". All others should be listed as children items. Please help figure what I'm doing wrong.
Here's the json input:
{
"clusterName": "ml6.engrlab.com-cluster",
"statusProperties": {
"loadProperties": {
"loadDetail": {
"restoreWriteLoad": {
"value": 0,
"units": "sec/sec"
},
},
"totalLoad": {
"value": 0.0825921967625618,
"units": "sec/sec"
}
},
"secure": {
"value": false,
"units": "bool"
},
"statusDetail": {
"licenseKeyOption": [
{
"value": "conversion",
"units": "enum"
},
{
"value": "failover",
"units": "enum"
}
],
"connectPort": 7999,
"softwareVersion": {
"value": 9000100,
"units": "quantity"
}
},
"rateProperties": {
"rateDetail": {
"largeReadRate": {
"value": 0,
"units": "MB/sec"
}
},
"totalRate": {
"value": 67.2446365356445,
"units": "MB/sec"
}
},
"online": {
"value": true,
"units": "bool"
},
"cacheProperties": {
"cacheDetail": {
"tripleCachePartitions": {
"tripleCachePartition": [
{
"partitionSize": 768,
"partitionBusy": 0,
"partitionUsed": 0,
"partitionFree": 100
}
]
}
}
}
}
}
my code
function isNested(obj) {
if(!obj) return false;
let propArry = Object.keys(obj)
for(let i=0; i<propArry.length; i++){
if(obj[propArry[0]].constructor.name === 'Object') return true
}
return false;
}
function getKeyValueAsChildren(obj) {
let vals = [];
for(let key in obj) {
if(obj.hasOwnProperty(key)){
vals.push({key:key, value: obj[key]})
}
}
return vals
}
function valueAsString(obj) {
if(typeof obj !== 'object') return obj;
return `${obj['value']} ${obj['units']}`
}
function getChildren(key, obj) {
if(Object.keys(obj).sort().toString() === "units,value"){
return {key: key, value: valueAsString(obj)}
} else {
return {key: key, children: getKeyValueAsChildren(obj) }
}
}
function getValues(properties, values = []) {
for(let key in properties) {
if(properties.hasOwnProperty(key)) {
let value = properties[key]
if(typeof value !== 'object') {
values.push({key: key, value: value})
} else if(Array.isArray(value)){
let children = []
value.map(v => {
children.push(getChildren(key, v))
})
values.push({key: `${key}List`, children: children})
}
else if(value.constructor.name === 'Object' && isNested(value)){
// I THINK THE MAIN PROBLEM IS HERE
let keys = Object.keys(value)
let children = [];
keys.forEach(key => {
children.push({key: key, children: getValues(value[key])})
})
values.push({key: key, children: children})
}
else {
values.push(getChildren(key, value))
}
}
}
return values
}
getValues(hostProperties)
this returns
[
{
"key": "clusterName",
"value": "ml6.engrlab.com-cluster"
},
{
"key": "statusProperties",
"children": [
{
"key": "loadProperties",
"children": [
{
"key": "loadDetail",
"children": [
{
"key": "restoreWriteLoad",
"children": [
{
"key": "value",
"value": 0
},
{
"key": "units",
"value": "sec/sec"
}
]
}
]
},
{
"key": "totalLoad",
"value": "0.0825921967625618 sec/sec"
}
]
},
{
"key": "secure",
"children": [
{
"key": "value",
"value": false
},
{
"key": "units",
"value": "bool"
}
]
},
{
"key": "statusDetail",
"children": [
{
"key": "licenseKeyOptionList",
"children": [
{
"key": "licenseKeyOption",
"value": "conversion enum"
},
{
"key": "licenseKeyOption",
"value": "failover enum"
}
]
},
{
"key": "connectPort",
"value": 7999
},
]
},
{
"key": "rateProperties",
"children": [
{
"key": "rateDetail",
"children": [
{
"key": "largeReadRate",
"children": [
{
"key": "value",
"value": 0
},
{
"key": "units",
"value": "MB/sec"
}
]
}
]
},
{
"key": "totalRate",
"value": "67.2446365356445 MB/sec"
}
]
},
{
"key": "online",
"children": [
{
"key": "value",
"value": true
},
{
"key": "units",
"value": "bool"
}
]
},
{
"key": "cacheProperties",
"children": [
{
"key": "cacheDetail",
"children": [
{
"key": "tripleCachePartitions",
"children": [
{
"key": "tripleCachePartitionList",
"children": [
{
"key": "tripleCachePartition",
"children": [
{
"key": "partitionSize",
"value": 768
},
{
"key": "partitionBusy",
"value": 0
},
{
"key": "partitionUsed",
"value": 0
},
{
"key": "partitionFree",
"value": 100
}
]
}
]
}
]
}
]
}
]
}
]
}
]
but I need this
[
{
"key": "clusterName",
"value": "ml6.engrlab.com-cluster"
},
{
"key": "statusProperties",
"children": [
{
"key": "loadProperties",
"children": [
{
"key": "loadDetail",
"children": [
{
"key": "restoreWriteLoad",
"value": "0 sec/sec"
}
]
},
{
"key": "totalLoad",
"value": "0.0825921967625618 sec/sec"
}
]
},
{
"key": "secure",
"value": "false bool"
},
{
"key": "statusDetail",
"children": [
{
"key": "licenseKeyOptionList",
"children": [
{
"key": "licenseKeyOption",
"value": "conversion enum"
},
{
"key": "licenseKeyOption",
"value": "failover enum"
}
]
},
{
"key": "connectPort",
"value": 7999
}
]
},
{
"key": "rateProperties",
"children": [
{
"key": "rateDetail",
"children": [
{
"key": "largeReadRate",
"value": "0 MB/sec"
}
]
},
{
"key": "totalRate",
"value": "67.2446365356445 MB/sec"
}
]
},
{
"key": "online",
"value": "true bool"
},
{
"key": "cacheProperties",
"children": [
{
"key": "cacheDetail",
"children": [
{
"key": "tripleCachePartitions",
"children": [
{
"key": "tripleCachePartitionList",
"children": [
{
"key": "tripleCachePartition",
"children": [
{
"key": "partitionSize",
"value": 768
},
{
"key": "partitionBusy",
"value": 0
},
{
"key": "partitionUsed",
"value": 0
},
{
"key": "partitionFree",
"value": 100
}
]
}
]
}
]
}
]
}
]
}
]
}
]
You might have to run more tests, as what you require seems quite arbitrary, but I believe this function does what you are looking for. It works in a similar way to yours, by simply recursing the tree, and checking for object types, and if the special case is matched.
function toKeyValue(obj) {
return Object.keys(obj).map(k => {
var value = obj[k]
var key = k
var valueName = 'children'
if(Array.isArray(value)){
key = k + 'List'
value = value.map(toKeyValue)
}else if(value !== null && typeof value === 'object'){
// check for special case
if(Object.keys(value).sort().toString() === "units,value"){
value = value.value + ' ' + value.units
valueName = 'value'
}else{
value = toKeyValue(value)
}
}else{
valueName = 'value'
}
return {
key: key,
[valueName]: value
}
})
}
Fiddle here