get size of value in a map javascript - javascript

I have below array object of key of Id and List of value pair. I want to get for each key what is the length of the value like
[
{
"key": "a5a5E0000003uzTQAQ",
"value": 1
},
{
"key": "a5a5E0000003uzYQAQ",
"value": 2
}
]
I am trying below code , but it is giving me undefined in the length of the value.
var message = [
{
"key": "a5a5E0000003uzTQAQ",
"value": [
{
"Name": "Features1"
}
]
},
{
"key": "a5a5E0000003uzYQAQ",
"value": [
{
"Name": "AEO Analysis - Engagement"
},
{
"Name": "AEO Analysis - Engagement 1",
}
]
}
]
let noOfFields = []
for (let key in message) {
if (message.hasOwnProperty(key)) {
noOfFields.push({key: key, value: message[key].length });
}
}
console.log(noOfFields)

You can use array.map
const message = [
{
"key": "a5a5E0000003uzTQAQ",
"value": [
{
"Name": "Features1"
}
]
},
{
"key": "a5a5E0000003uzYQAQ",
"value": [
{
"Name": "AEO Analysis - Engagement"
},
{
"Name": "AEO Analysis - Engagement 1",
}
]
}
]
const noOfFields = message.map((obj) => {
return {
key: obj.key,
value: obj.value.length
}
})
console.log(noOfFields)
Result:
[
{ key: 'a5a5E0000003uzTQAQ', value: 1 },
{ key: 'a5a5E0000003uzYQAQ', value: 2 }
]

If you want the length you just need this:
var message = [
{
"key": "a5a5E0000003uzTQAQ",
"value": [
{
"Name": "Features1"
}
]
},
{
"key": "a5a5E0000003uzYQAQ",
"value": [
{
"Name": "AEO Analysis - Engagement"
},
{
"Name": "AEO Analysis - Engagement 1",
}
]
}
]
let noOfFields = []
for (let key in message) {
if (message.hasOwnProperty(key)) {
noOfFields.push({key: key, value: message[key].value.length });
}
}
console.log(noOfFields)
It's a little misleading to call the length of the value 'value' though.

Related

How do I destructure this deep nested json objects and map it in JS

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;
}

Recursion not returning right result

I am working on a problem where I would like to transform the following object structure:
[
{
"label": "testType",
"categories": [
{
"label": "testCatType",
"subCategories": [
{
"label": "newSubCat",
"subSubCategories": [
{
"label": "newSubSubCat1"
},
{
"label": "newSubSubCat2"
},
{
"label": "newSubSubCat3"
}
]
}
]
}
]
},
{
"label": "newType",
"categories": [
{
"label": "newCat10",
"subCategories": [
{
"label": "newCatSub1",
"subSubCategories": [
{
"label": "bingo11"
},
{
"label": "bingo12"
},
{
"label": "bingo15"
}
]
}
]
}
]
},
{
"label": "displacement",
"categories": []
},
{
"label": "brush",
"categories": [
{
"label": "blood",
"subCategories": []
},
{
"label": "damage",
"subCategories": []
},
]
}
]
into something like this:
{
"testType": {
"testCatType": {
"newSubCat": {
"newSubSubCat1": {},
"newSubSubCat2": {},
"newSubSubCat3": {}
}
}
},
"newType": {
"newCat10": {
"newCatSub1": {
"bingo11": {},
"bingo12": {},
"bingo15": {}
}
}
},
"displacement": {},
....
}
I have implemented the following recursive solution for this:
recursiveAssign(obj, json) {
if (_.isUndefined(obj)) {
return;
}
let totalKeys = _.keys(obj);
return _.assign(json, { [obj['label']]: this.test(obj[totalKeys[1]], json) })
}
transform(typeObj){
let json = {};
_.forEach(typeObj, obj => {
let totalKeys = _.keys(obj);
if (totalKeys < 2) {
_.assign(json, obj['label']);
} else {
_.assign(json, { [obj['label']]: this.recursiveAssign(obj[totalKeys[1]], json) })
}
})
}
Now the end result of this is an object that is a copy of itself on each level and I don't quite understand what the problem is. I think my approach is not faulty as I take the label and call the recursive function on the other part of that object. Can please someone point out to the potential issue!
You can write transform as a simple recursive function -
function transform (all = []) {
return Object.fromEntries(all.map(t =>
[t.label, transform(t.categories ?? t.subCategories ?? t.subSubCategories)]
))
}
const data =
[{"label":"testType","categories":[{"label":"testCatType","subCategories":[{"label":"newSubCat","subSubCategories":[{"label":"newSubSubCat1"},{"label":"newSubSubCat2"},{"label":"newSubSubCat3"}]}]}]},{"label":"newType","categories":[{"label":"newCat10","subCategories":[{"label":"newCatSub1","subSubCategories":[{"label":"bingo11"},{"label":"bingo12"},{"label":"bingo15"}]}]}]},{"label":"displacement","categories":[]},{"label":"brush","categories":[{"label":"blood","subCategories":[]},{"label":"damage","subCategories":[]},]}]
console.log(JSON.stringify(transform(data), null, 2))
{
"testType": {
"testCatType": {
"newSubCat": {
"newSubSubCat1": {},
"newSubSubCat2": {},
"newSubSubCat3": {}
}
}
},
"newType": {
"newCat10": {
"newCatSub1": {
"bingo11": {},
"bingo12": {},
"bingo15": {}
}
}
},
"displacement": {},
"brush": {
"blood": {},
"damage": {}
}
}
You can chain ... ?? t.subSubSubCategories and ... ?? t.subSubSubSubCategories, if needed. A better approach would be to create a consistent node interface for all nodes in your graph. You could achieve this by renaming all sub*Categories to simply categories. This will give each node an inteface like
Node: { label: String, categories: Array<Node> }
You can solve this in pure js like this:
const arr = [{ "label": "testType", "categories": [{ "label": "testCatType", "subCategories": [{ "label": "newSubCat", "subSubCategories": [{ "label": "newSubSubCat1" }, { "label": "newSubSubCat2" }, { "label": "newSubSubCat3" }] }] }] }, { "label": "newType", "categories": [{ "label": "newCat10", "subCategories": [{ "label": "newCatSub1", "subSubCategories": [{ "label": "bingo11" }, { "label": "bingo12" }, { "label": "bingo15" }] }] }] }, { "label": "displacement", "categories": [] }, { "label": "brush", "categories": [{ "label": "blood", "subCategories": [] }, { "label": "damage", "subCategories": [] }, ] }];
let result = recursive(arr);
console.log(result);
function recursive(arr) {
let result = {};
let returnValue = {}
for (let obj of arr) {
let entries = Object.entries(obj);
if (!entries.length) {
return {};
}
for (let [key, value] of entries) {
if (typeof value == "object") {
result = recursive(value);
}
}
const label = obj["label"];
returnValue = { ...returnValue,
[obj["label"]]: result
};
}
return returnValue;
}
.as-console-wrapper {min-height: 100%;}

Javascript Json formatting

I've a json like below
[
{
"name": "Item",
"attribute_list": [
{
"name": "Attribute 1",
"value_list": [
{
"value": "1"
},
{
"value": "2"
}
]
},
{
"name": "Attribute 2",
"value_list": [
{
"value": "10"
},
{
"value": "60"
},
{
"value": "80"
}
]
}
]
}
]
I want to change format like below
[
{
"Item": [{
"Attribute 1": "1", "Attribute 2": "10"
}]
}
]
What I've done already:
results.map(items => {
data[items.name.toLowerCase().replace(/ /g, '_')] = items.attribute_list?
items.attribute_list.reduce(
(obj, item) => Object.assign(obj, { [item.name.toLowerCase().replace(/ /g, '_')]: item.value_list?item.value_list[0].value:null }), {})
:null
})
Thanks in advance
If I understood everything correctly, you can do it like this:
const input = [
{
"name": "Item",
"attribute_list": [
{
"name": "Attribute 1",
"value_list": [
{
"value": "1"
},
{
"value": "2"
}
]
},
{
"name": "Attribute 2",
"value_list": [
{
"value": "10"
},
{
"value": "60"
},
{
"value": "80"
}
]
}
]
}
];
const result = input.map((entry) => {
return {
[entry.name]: [entry.attribute_list.reduce((res, curr) => {
res[curr.name] = curr.value_list[0].value;
return res;
}, {})]
};
});
console.log(result);

transforming json using recursive function

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

Building new JSON from existing one

I want to build an new JSON from existing one. The source has sections and rubrics that I no longer need for a listing. The new object called 'items' should have an array of the items.
The final JSON should be sorted by attribute 'name' and look like
{
"items": [
{
"id": 10000006,
"name": "Boah"
},
{
"id": 10000013,
"name": "Gut"
},
{
"id": 10000003,
"name": "Ipsum"
},
{
"id": 10000001,
"name": "Lorem"
},
{
"id": 10000005,
"name": "Lorum"
},
{
"id": 10000004,
"name": "Name"
},
{
"id": 10000002,
"name": "Stet"
}
]
}
For building the new JSON I get this source:
{
"sections": [
{
"name": "FooBar",
"rubrics": [
{
"name": "Foo",
"items": [
{
"id": 10000001,
"name": "Lorem"
},
{
"id": 10000002,
"name": "Stet"
},
{
"id": 10000003,
"name": "Ipsum"
}
]
},
{
"name": "Bar",
"items": [
{
"id": 10000004,
"name": "Name"
},
{
"id": 10000005,
"name": "Lorum"
},
{
"id": 10000006,
"name": "Boah"
}
]
}
]
},
{
"name": "BlahBloob",
"rubrics": [
{
"name": "Bla",
"items": [
{
"id": 10000013,
"name": "Gut"
}
]
},
{
"name": "Bloob",
"items": [
{
"id": 10000014,
"name": "Name"
},
{
"id": 10000015,
"name": "Lorem"
}
]
}
]
}
]
}
What do you think? How can I do this with plain JavaScript or maybe TypeScript?
Thanks for reading and have time for my question. And thanks for reply in advance.
Here you go. You just need to iterate over each rubric of each section of your source to get the items. At the end, sort your list of items by items, and you're done.
This example uses ES6 syntax, but it's easy to convert it to ES5 if needed.
function extractItems(source) {
const items = [];
for (const section of source.sections) {
for (const rubric of section.rubrics) {
items.push(...rubric.items);
}
}
items.sort((a, b) => a.name.localeCompare(b.name));
return { items };
}
A more functional approach use map and reduce to pick the rubrics and merge them.
data.sections
.map(section => section.rubrics) // get rubrics
.reduce((a, b) => a.concat(b)) // merge rubrics
.map(rubric => rubric.items) // get items from each rubric
.reduce((a, b) => a.concat(b)) // merge items
.sort((a, b) => a.name.localeCompare(b.name)); // sort
function(oldObj) {
var newObj = {
"items": []
};
oldObj.sections.forEach(function(section) {
section.rubrics.forEach(function(rubric) {
rubric.items.forEach(function(item) {
newObj.items.push(item);
});
});
});
newObj.items = newObj.items.sort(function(a, b) {
if (a.name < b.name) { return -1; }
if (a.name > b.name) { return 1; }
return 0;
});
return newObj;
}
And simply use JSON.parse() and JSON.stringify() to convert JSON to and from objects.
It might help you
var data ={
"sections": [
{
"name": "FooBar",
"rubrics": [{"name": "Foo", "items": [{"id": 10000001,"name": "Lorem"}, {"id": 10000002,"name": "Stet"}, {"id": 10000003,"name": "Ipsum"}]
}, {
"name": "Bar",
"items": [{
"id": 10000004,
"name": "Name"
}, {
"id": 10000005,
"name": "Lorum"
}, {
"id": 10000006,
"name": "Boah"
}]
}]
}, {
"name": "BlahBloob",
"rubrics": [{
"name": "Bla",
"items": [{
"id": 10000013,
"name": "Gut"
}]
}, {
"name": "Bloob",
"items": [{
"id": 10000014,
"name": "Name"
}, {
"id": 10000015,
"name": "Lorem"
}]
}]
}]
};
var itemObj = {};
var itemArr = [];
var sections = data.sections;
for(var i=0;i<sections.length;i++)
{
for(var j=0;j<sections[i].rubrics.length;j++){
for(var k=0;k<sections[i].rubrics[j].items.length;k++){
var itemObj;
itemObj['id'] = sections[i].rubrics[j].items[k].id;
itemObj['name'] = sections[i].rubrics[j].items[k].name;
itemArr.push(itemObj);
}
}
}
var finalObj = {"items":itemArr};
console.log(finalObj);
JSFiddle

Categories

Resources