I receive a JSON result message in the following format from an old database query that I do not have the ability to change at this time:
{
"vsm1": "2429",
"vsm2": "2488",
"vsm3": "1968",
"vsm4": "",
"vsm5": "",
"vsm6": "",
"vsm7": "",
"vsm8": "",
"vsm9": "",
"vsm10": "",
"color1": "5",
"color2": "4",
"color3": "4",
"color4": "0",
"color5": "0",
"color6": "0",
"color7": "0",
"color8": "0",
"color9": "0",
"color10": "0",
"p1mtime": "1549296004",
"p2mtime": "1549296009",
"p3mtime": "1549296014",
"p4mtime": "",
"p5mtime": "",
"p6mtime": "",
"p7mtime": "",
"p8mtime": "",
"p9mtime": "",
"p10mtime": "",
"inch1": "",
"inch2": "",
"inch3": "",
"inch4": "",
"inch5": "",
"inch6": "",
"inch7": "",
"inch8": "",
"inch9": "",
"inch10": ""
}
I would like to re-format it to a more useable object, like so:
{ id: 1, vsm: 2429, color: 5, pmtime: 1549296004, inch: 0 }
{ id: 2, vsm: 2488, color: 4, pmtime: 1549296009, inch: 0 }
{ id: 3, vsm: 1968, color: 4, pmtime: 1549296014, inch: 0 }
...and so on.
The incoming data is currently limited to ten of each 'section' (vsm1, vsm2, ...vsm10, color1, color2, ...color10, etc.), so a static loop of some sort over the ten elements in each section is how i started, but seemed rather ugly and certainly not flexible.
A smart snippet that would handle n-number of elements in each section would be even better just in case the data goes beyond ten elements, or drops to just three (due to absence of data or pruned data).
I'm thinking of something along the lines of using .forEach(), but admittedly my JSON / Object manipulation skills are rather poor, so I turn to the community in the hope that someone can point me in the right direction or knows of a cool, tight routine/function that achieves what I'm looking for. Thanks in advance for any insights.
You could take an array of the wanted keys with a placeholder for the running number and build new object and push them to the result set.
var data = { vsm1: "2429", vsm2: "2488", vsm3: "1968", vsm4: "", vsm5: "", vsm6: "", vsm7: "", vsm8: "", vsm9: "", vsm10: "", color1: "5", color2: "4", color3: "4", color4: "0", color5: "0", color6: "0", color7: "0", color8: "0", color9: "0", color10: "0", p1mtime: "1549296004", p2mtime: "1549296009", p3mtime: "1549296014", p4mtime: "", p5mtime: "", p6mtime: "", p7mtime: "", p8mtime: "", p9mtime: "", p10mtime: "", inch1: "", inch2: "", inch3: "", inch4: "", inch5: "", inch6: "", inch7: "", inch8: "", inch9: "", inch10: "" },
keys = ['vsm*', 'color*', 'p*mtime', 'inch*'],
result = [],
id = 1;
while (keys[0].replace('*', id) in data) {
result.push(Object.assign(
{ id },
...keys.map(k => ({ [k.replace('*', '')]: +data[k.replace('*', id)] || 0 }))
));
id++;
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
With template literals
var data = { vsm1: "2429", vsm2: "2488", vsm3: "1968", vsm4: "", vsm5: "", vsm6: "", vsm7: "", vsm8: "", vsm9: "", vsm10: "", color1: "5", color2: "4", color3: "4", color4: "0", color5: "0", color6: "0", color7: "0", color8: "0", color9: "0", color10: "0", p1mtime: "1549296004", p2mtime: "1549296009", p3mtime: "1549296014", p4mtime: "", p5mtime: "", p6mtime: "", p7mtime: "", p8mtime: "", p9mtime: "", p10mtime: "", inch1: "", inch2: "", inch3: "", inch4: "", inch5: "", inch6: "", inch7: "", inch8: "", inch9: "", inch10: "" },
templates = [id => `vsm${id}`, id => `color${id}`, id => `p${id}mtime`, id => `inch${id}`],
result = [],
id = 1;
while (templates[0](id) in data) {
result.push(Object.assign(
{ id },
...templates.map(t => ({ [t('')]: +data[t(id)] || 0 }))
));
id++;
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Try this, with oldObject the object you want to clean:
var cleanedObject = {};
for (let [key, value] of Object.entries(oldObject)) {
let index = key.match('[0-9]+');
cleanedObject[index] = cleanedObject[index] || {};
cleanedObject[index][key.replace(index, '')] = value;
}
The result will be an object where cleanedObject['1'] = { vsm: 2429, color: 5, pmtime: 1549296004, inch: '' }, and so on.
This solution has a different flexibility than the one from Nina Sholz. Nina's allows you to match any style of number-containing key. But it also requires you to add a template in order to do so. Mine will handle any keys which contain only a single run of digits but nothing more complex. But it doesn't require you to do anything to handle such templates.
const reformat = data => Object.values(Object.keys(data)
.reduce(
(a, k, i, _, d = k.match(/\d+/)[0]) => ({
...a,
[d]: {...(a[d] || {id: Number(d)}), [k.replace(/\d+/, '')]: data[k]}
}), {})).sort((a, b) => a.id - b.id)
const data = {"vsm1":"2429","vsm2":"2488","vsm3":"1968","vsm4":"","vsm5":"","vsm6":"","vsm7":"","vsm8":"","vsm9":"","vsm10":"","color1":"5","color2":"4","color3":"4","color4":"0","color5":"0","color6":"0","color7":"0","color8":"0","color9":"0","color10":"0","p1mtime":"1549296004","p2mtime":"1549296009","p3mtime":"1549296014","p4mtime":"","p5mtime":"","p6mtime":"","p7mtime":"","p8mtime":"","p9mtime":"","p10mtime":"","inch1":"","inch2":"","inch3":"","inch4":"","inch5":"","inch6":"","inch7":"","inch8":"","inch9":"","inch10":""}
console.log(reformat(data))
I have no idea if you need either sort of flexibility, but these are interesting alternatives to one another.
I now see that my answer is basically the same as Ninas, haven't seen templating before so that was cool, but seeing as this i the first time i've tried to answer something here I'll just share it anyway.
As Ninas this can handle any length of data.
const data = {"vsm1": "2429",
"vsm2": "2488",
"vsm3": "1968",
"vsm4": "",
"color1": "5",
"color2": "4",
"color3": "4",
"color4": "0",
"p1mtime": "1549296004",
"p2mtime": "1549296009",
"p3mtime": "1549296014",
"p4mtime": "",
"inch1": "",
"inch2": "",
"inch3": "",
"inch4": "",
};
const vsmRegex = new RegExp("(vsm\\d)");
const keys = Object.keys(data);
const result = [];
let id= 1;
for(let i = 0; i < keys.length; i++) {
if(keys[i].match(vsmRegex)) {
let object = {
id: id,
vsm: Number(data[`vsm${id}`]) || 0,
color: Number(data[`color${id}`]) || 0,
pmtime: Number(data[`p${id}mtime`]) || 0,
inch: Number(data[`inch${id}`]) || 0
};
result.push(object);
id++;
} else {
break;
}
}
console.log(result);
Related
I am preparing an array like this
datas[5] = { "qty_sized": "1", "resolution": "5", "status": "", "order": 1342 };
where [5] is dynamic from response.
I have and object mydata and inside that I have a object items.
I push array to object items, with assign
Object.assign(mydatadata.items, datas);
Now mydata.items has an array set,
`
items{
1 {qty_auth: "", resolution: "4", status: "", order: "1495"},
5 {qty_sized: "1", resolution: "4", status: "", order: "1485"}
}`
Now if qty_auth: "" , from which i need to check if qty_ is empty then remove the array . So expected output is something like this:
Note: qty_ is dynamic here.
items{ 5 {qty_sized: "1", resolution: "4", status: "", order: "1485"} }
and i want to result inside same object mydata.items
I tried something like this
const mydatadata.items = mydata.items.filter((o) =>
Object.keys(o).some((k) => k.startsWith("qty") && o[k])
);
console.log(result);
but its now giving me any output
Using Object#entries, get the key-value pairs of items
Using Array#filter, iterate over the above array
In each iteration, check if the current item has a key starting with qty_ whose value is not empty. You can do this using Object#keys, Array#some, and String#startsWith.
Using Object#fromEntries, convert the filtered pairs to an object again.
const obj = {
items: {
1: {qty_auth: "", resolution: "4", status: "", order: "1495"},
5: {qty_sized: "1", resolution: "4", status: "", order: "1485"}
}
};
obj.items = Object.fromEntries(
Object.entries(obj.items)
.filter(([_, item]) =>
Object.keys(item).some(key => key.startsWith('qty_') && item[key])
)
);
console.log(obj);
You're talking about an array, but using curly brackets instead of square brackets. For filter() to work it would have to look like:
mydata = {
items: [
{qty_auth: "", resolution: "4", status: "", order: "1495"},
{qty_sized: "1", resolution: "4", status: "", order: "1485"}
]
}
Assuming it is an actual array there's still a problem with "const mydatadata.items", or at least it throws an error for me because mydatadata is not initialized. Unless it's a typo and it should be mydata, but then you'd be redeclaring it. So depending on what you want:
mydata.items = mydata.items.filter((o) =>
Object.keys(o).some((k) => k.startsWith("qty") && o[k])
);
or
let mydatadata = {};
mydatadata.items = mydata.items.filter((o) =>
Object.keys(o).some((k) => k.startsWith("qty") && o[k])
);
Furthermore you're storing the result in mydatadata but you're logging the variable result.
So depending on the previous answer:
console.log(mydatadata);
or
console.log(mydata);
Here's a fiddle: https://jsfiddle.net/b57qa82d/
You should probably just be using an array rather than an object. It's not really clear from your question what structure you need as you keep changing the terminology to describe your data. For example: "Now mydata.items has an array set" but your code says that it should be object with keys, not an array.
So I suggest: get your data in an array, and filter it by iterating over each object's entries and checking to see if any of the keys starting with "qty" has a value that isn't an empty string. You can then assign that filtered array to myObject.items.
const data = [
{ "qty_sized": "0", "resolution": "5", "status": "", "order": 2 },
{ "qty_auth": "", "resolution": "5", "status": "", "order": 3 },
{ "qty_auth": "1", "resolution": "5", "status": "", "order": 1342 },
{ "qty_sized": "", "resolution": "2", "status": "", "order": 1 },
{ "qty_sized": "1", "resolution": "1", "status": "", "order": 142 }];
const filtered = data.filter(obj => {
return Object.entries(obj).find(([key, value]) => {
return key.startsWith('qty') && value;
});
});
const myObject = { items: filtered };
console.log(myObject);
Additional documentation
Object.entries
find
I have an array like:
["", "", "", "1", "", ""]
I want to alert when all the array values are blanks, i.e, when the array is like this:
["", "", "", "", "", ""]
How can I achieve this.
Use every():
const allEmpty = arr => arr.every(e => e === "");
console.log(allEmpty(["", "", "", "1", "", ""]));
console.log(allEmpty(["", "", "", "", "", ""]));
Try this,
["", "", "", "", "", ""].join("").length==0
If you want to remove spaces,
["", "", "", "", "", ""].join("").replace(/\s/gi,'').length==0
Note :
This will not work for inputs like ["", [], "", null, undefined, ""]
TL;DR (Fastest & Simple)
[].some(Boolean) // Empty : false | Not Empty : true
Explanation
Mixture of native functions, Boolean with .some() or .filter() or using .join() can return the expected result:
var a=['','','','',''], // Empty
b=['','','x','','']; // Not Empty
// Is Not Empty?
// #1
console.log( a.some(Boolean) ); // false
console.log( b.some(Boolean) ); // true
// #2
console.log( a.filter(Boolean).length ); // = 0
console.log( b.filter(Boolean).length ); // != 0
// #3
console.log( a.join('')!='' ); // false
console.log( b.join('')!='' ); // true
Also a user-defined function:
var a=['','','','',''], // Empty
b=['','','x','','']; // Not Empty
function isArrayEmpty(a) {
for (var i = 0; i < a.length; i++)
if (a[i]) return false;
return true;
}
console.log( isArrayEmpty(a) ); // true
console.log( isArrayEmpty(b) ); // false
But about performance:
.some(Boolean) ~40M ops/s (Operation per second)
isArrayEmpty() ~36M ops/s (~10% slower)
.filter(Boolean).length ~9M ops/s (~75% slower)
.join('')!='' ~4M ops/s (~90% slower)
Note (1): Using Arrow functions (a)=>a instead of Boolean, will make the performances even lower, in these cases about ~5% slower.
Note (2): The expected result is same just when we are sure that all of array items are String. About other falsy s (null or false ...) items, the option #3 (join) will not work.
You can always use a basic for loop as a solution for your problem:
function allBlanks(arr)
{
for (var i = 0; i < arr.length; i++)
{
if (arr[i] !== "") return false;
}
return true;
}
console.log(allBlanks(["", "", "", "1", "", ""]));
console.log(allBlanks(["", "", "", "", "", ""]));
console.log(allBlanks(["", [], "", null, undefined, ""]));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
Here is also a more generic approach which would compact the array removing all falsey values and then check the remaining length:
let compact = a => a.reduce((r,c) => (!!c ? r.push(c) : null, r),[])
let isEmpty = array => compact(array).length == 0
console.log(isEmpty(["", false, 0, "", null, undefined])) // true
console.log(isEmpty(["", 1])) // false
console.log(isEmpty(["", []])) // false
console.log(isEmpty(["", {}])) // false
But if this is the only use case you care about then you can also use Array.some:
let isEmpty = a => !a.some(x => x !== '')
// OR let isEmpty = a => !a.some(x => x.toString().length > 0)
console.log(isEmpty(["", "", "", "", "", ""]))
console.log(isEmpty(["", "", "1", "", "", ""]))
You could also use Array.reduce:
let isEmpty = a => !a.reduce((r,c) => `${r}${c}`).length
console.log(isEmpty(["", "", "", "", "", ""]))
console.log(isEmpty(["", "", "1", "", "", ""]))
Array.filter:
let isEmpty = a => !a.filter(x => x.toString().length).length
console.log(isEmpty(["", "", "", "", "", ""]))
console.log(isEmpty(["", "", "1", "", "", ""]))
This will only be valid check against your current input however. Not against cases with arrays, object literals etc as part of your input array.
If you are using lodash this could be (via _.every and _.isEmpty):
let isArrayEmpty = a => _.every(a, _.isEmpty)
console.log(isArrayEmpty(["", "", "", "", "", ""]))
console.log(isArrayEmpty(["", "", "1", "", "", ""]))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
or also via _.compact which also removes falsey values:
let isArrayEmpty = a => !_.compact(a).length
console.log(isArrayEmpty(["", "", "", "", "", ""]))
console.log(isArrayEmpty(["", "", "1", "", "", ""]))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
const isEmpty=arr=>{
return arr.filter(it=>it.length>0).length ==0
}
arr1 = ["",""]
arr2 = ["1",""]
console.log(isEmpty(arr1))
console.log(isEmpty(arr2))
var arr1 = ["", "", "", "1", "", ""];
var arr2 = ["", "", "", "", "", ""];
function checkArrValEmpty(arr) {
let count = 0;
for(let i = 0; i < arr.length; i++) {
if(arr[i].trim().length === 0) {`enter code here`
count++;
}
}
return count === arr.length
}
console.log(checkArrValEmpty(arr2));
console.log(checkArrValEmpty(arr1));
function isEmpty (arr){
return arr.every(e => e === "")
};
let a = ["", "", "", "1", "", ""];
let b = ["", "", "", "", "", ""]
console.log(isEmpty(a));
console.log(isEmpty(b));
I implemented small function for checking empty array which will work in all browsers.
var list=["1", [], "", null, undefined, ""];
var listE=["", "", "","", "", "", ""];
var listE1=["", [], "", null, undefined, ""];
function isArrayEmpty(arr){
return arr.toString().replace(/,/g, '')=="";
}
alert(isArrayEmpty(list))
alert(isArrayEmpty(listE))
alert(isArrayEmpty(listE1))
1) Maintain the size of array as length 2) Find the no. of empty values in the array and store it in say an variable (EmptyValues)
3) Check if (EmptyValue== length) { Give Alert whatever you want}
function checkBlankvalues(arr){
var emptyValues=0,length=arr.length;
//for finding empty vales in array till now
for(var i=0;i<arr.length;i++)
{
if(arr[i]="")
{
emptyValues++;
}
}
if(length==emptyValue)
{
//alert("array is blank");
}
}
The Solution:
Thanks to #Kunal Mukherjee for the help.
const pattern = /\](,)\s{2,}?/gm
let res = inputData.rows.replace(pattern, (match, group1, offset, string) => "]")
.split(/\s{2,}/gm)
.map(x => JSON.parse(x));
res = res[0]; //reassign to scrape an array layer
let resultString = '';
for (let i = 0; i < res[0].length; i += 1) {
let cv = res[0][i];
if (cv.length === 0) resultString += ` ${res[1][i]}: ${inputData.rows[2][i]}\n`
else resultString += `${cv}\n ${res[1][i]}: ${res[2][i]}\n`;
}
output = {KPI: resultString};
Original Post:
The problem
In a Zapier Zap, I'm extracting data from Google Sheets and using JS to prettify it to later send in an email. I'm bumping into an error with the following message:
SyntaxError: Unexpected token ]
stringOfArraysToArrayOfArrays (eval at <anonymous> (/var/task/index.js:52:23), <anonymous>:22:52)
theFunction (eval at <anonymous> (/var/task/index.js:52:23), <anonymous>:29:18)
eval (eval at <anonymous> (/var/task/index.js:52:23), <anonymous>:51:20)
Domain.<anonymous> (/var/task/index.js:53:5)
Domain.run (domain.js:242:14)
module.exports.handler (/var/task/index.js:51:5)
What I've tried
I've successfully run this code from the most current version of Node back to Node v6.3.1 in different environments - local IDE, Repl.It IDE, and an online IDE set to Node v6.3.1. They all clear. I've also tried clearing the code of all ES6+ syntax (sans the example data)
Example of data
let inputData = {
rows: `["Prioritized Tasks", "", "", "", "Operational Tasks", "", "", "", "Eight Dimensions", "", "", "", "", "", "", "", "Burn-Out", "", "", "", "", "", "", "", "", "", "Violations"],
["Completion Rate", "Avg Completed", "Avg Total Scheduled", "Avg Time Spent", "Completion Rate", "Avg Completed", "Avg Total Scheduled", "Avg Time Spent", "Emotional", "Environmental", "Financial", "Intellectual", "Occupational", "Physical", "Social", "Spiritual", "Feeling Stressed", "Feeling Depleted", "Having Trouble Concentrating", "Feeling Forgetful", "Wanting to avoid social situations", "Feeling pessimistic", "Feeling cynical", "Feeling apathetic or disinterested", "Not feeling engaged with my work", "My overall energy level", "Temperance", "Silence", "Order", "Resolution", "Frugality", "Industry", "Sincerity", "Justice", "Moderation", "Cleanliness", "Tranquility", "Chastity", "Humility"],
["70.33", "4", "6.67", "380", "3.67", "3.67", "66.67", "100", "8", "5.33", "5.67", "4.67", "4", "5", "4.67", "6.67", "1.33", "4", "5", "4.67", "3.33", "3.33", "1.33", "5", "6", "5.67", "0.3333333333", "0.3333333333", "0.3333333333", "0", "1", "0", "0", "0", "0", "0.3333333333", "0.3333333333", "0.3333333333", "0.3333333333"]`
}
Code producing the error
function stringOfArraysToArrayOfArrays(string) {
let arrayPointers = [0, 1];
let arrOfArr = [];
for (let i = 0; i < string.length; i += 1) {
let cv = string[i];
if (cv === "[") arrayPointers[0] = i;
else if (cv === "]") {
arrayPointers[1] = i + 1;
arrOfArr.push(string.slice(arrayPointers[0], arrayPointers[1]));
arrOfArr[arrOfArr.length - 1] = eval(arrOfArr[arrOfArr.length - 1]);
}
}
return arrOfArr;
}
inputData.rows = stringOfArraysToArrayOfArrays(inputData.rows);
let resultString = '';
for (let i = 0; i < inputData.rows[0].length; i += 1) {
let cv = inputData.rows[0][i];
if (cv.length === 0) resultString += ' ' + inputData.rows[1][i] + ': ' + inputData.rows[2][i] + '\n';
else resultString += cv + '\n ' + inputData.rows[1][i] + ': ' + inputData.rows[2][i] + '\n';
}
output = {KPI: resultString};
Expected results
I'm expecting for the code to run, first off, then I'm expecting output.KPI to be a prettified string.
Thanks for the time & help :)
This approach may be a little functional.
You need to first replace the ], in every row to an empty string I have used this Regex to split it.
After that, I split the strings by whitespaces which are more than 2 characters.
Then finally I used .map to project over the splitted items to parse it back and make an array of array.
const inputData = {
rows: `["Prioritized Tasks", "", "", "", "Operational Tasks", "", "", "", "Eight Dimensions", "", "", "", "", "", "", "", "Burn-Out", "", "", "", "", "", "", "", "", "", "Violations"],
["Completion Rate", "Avg Completed", "Avg Total Scheduled", "Avg Time Spent", "Completion Rate", "Avg Completed", "Avg Total Scheduled", "Avg Time Spent", "Emotional", "Environmental", "Financial", "Intellectual", "Occupational", "Physical", "Social", "Spiritual", "Feeling Stressed", "Feeling Depleted", "Having Trouble Concentrating", "Feeling Forgetful", "Wanting to avoid social situations", "Feeling pessimistic", "Feeling cynical", "Feeling apathetic or disinterested", "Not feeling engaged with my work", "My overall energy level", "Temperance", "Silence", "Order", "Resolution", "Frugality", "Industry", "Sincerity", "Justice", "Moderation", "Cleanliness", "Tranquility", "Chastity", "Humility"],
["70.33", "4", "6.67", "380", "3.67", "3.67", "66.67", "100", "8", "5.33", "5.67", "4.67", "4", "5", "4.67", "6.67", "1.33", "4", "5", "4.67", "3.33", "3.33", "1.33", "5", "6", "5.67", "0.3333333333", "0.3333333333", "0.3333333333", "0", "1", "0", "0", "0", "0", "0.3333333333", "0.3333333333", "0.3333333333", "0.3333333333"]`
};
const pattern = /\](,)\s{2,}?/gm
const res = inputData.rows.replace(pattern, (match, group1, offset, string) => "]")
.split(/\s{2,}/gm)
.map(x => JSON.parse(x));
const output = { KPI: res };
console.log(output);
I have an object literal or like a json file which has data in it, what I want is to wrap the SMBPremium and MAX data inside an array so that I can target by accessing its index. How Can I modify my object literal to an array so that I can target SMBPremium and MAX. Kinda like this.
productMap['TEC0'][1].productName;
This is my json
var productMap = {
"TEC0": {
"SMBPremium" : {
"productName": "Wilson",
"panelClass": "WilsonClass",
"fullinfoClass": "Wilsonfull",
"productPageLink": "",
"panelPageLinkGA": "",
"fullPageLinkGA": "",
"notifLinkDanger" : {
"linkPrimary" : "",
"linkSecondary" : ""
},
"notifLinkRed" : {
"linkPrimary" : "",
"linkSecondary" : ""
},
"notifLinkInfo" : "",
"notifLinkWarning" : "",
"notifLinkSuccess" : ""
},
"MAX": {
"productName": "Spalding",
"panelClass": "spalding",
"fullinfoClass": "spalding",
"productPageLink": "",
"panelPageLinkGA": "",
"fullPageLinkGA": "",
"notifLinkDanger" : {
"linkPrimary" : "",
"linkSecondary" : ""
},
"notifLinkRed" : {
"linkPrimary" : "",
"linkSecondary" : ""
},
"notifLinkInfo" : "",
"notifLinkWarning" : "",
"notifLinkSuccess" : ""
}
}
};
Tranform with array.map:
productMap2 = {};
productMap2.TEC0 = Object.keys(productMap['TEC0']).map(key => productMap['TEC0'][key]);
Then you can access productName property for each element:
productMap2.TEC0[1].productName
You can recreate the object productMap formatted like you wish:
// Every object is a map:
var tec0 = productMap['TEC0'];
var keys = Object.keys(tec0);
var array = [];
for(var i=0; i<keys.length; i++) {
var key = keys[i];
var value = tec0[key];
array.push(value);
}
var newProductMap = {'TEC0': array};
alert(newProductMap['TEC0'][1].productName);
NOTE: Faly's answer is far more elegant. Just be carefull at browser compatibility with arrow functions (IE does not support for example).
Idem for Ammar's answer, not supported by IE.
Use Object.values() method:
productMap["TEC0"] = Object.values(productMap["TEC0"]);
try this
index = 1
productMap['TEC0'][Object.keys(productMap['TEC0'])[index]].productName;
Explanation
productMap['TEC0'] is an json object
Object.keys(productMap['TEC0']) - will return json object keys as array.
in this example like this ["SMBPremium", "MAX"]
Object.keys(productMap['TEC0'])[index] - will return key name based
on index passed.
productMap['TEC0'][key_name] - will fetch json object based
key_name got from previous state.
You could map the items to an index of the wanted keys array.
var productMap = { TEC0: { SMBPremium: { productName: "Wilson", panelClass: "WilsonClass", fullinfoClass: "Wilsonfull", productPageLink: "", panelPageLinkGA: "", fullPageLinkGA: "", notifLinkDanger: { linkPrimary: "", linkSecondary: "" }, notifLinkRed: { linkPrimary: "", linkSecondary: "" }, notifLinkInfo: "", notifLinkWarning: "", notifLinkSuccess: "" }, MAX: { productName: "Spalding", panelClass: "spalding", fullinfoClass: "spalding", productPageLink: "", panelPageLinkGA: "", fullPageLinkGA: "", notifLinkDanger: { linkPrimary: "", linkSecondary: "" }, notifLinkRed: { linkPrimary: "", linkSecondary: "" }, notifLinkInfo: "", notifLinkWarning: "", notifLinkSuccess: "" } } },
keys = ['SMBPremium', 'MAX'];
keys.forEach((k, i) => productMap.TEC0[i] = productMap.TEC0[k]);
console.log(productMap['TEC0'][0].productName);
I'm receiving this JSON below
{
"category": "test",
"sealing_temp_1": "",
"sealing_temp_2": "",
"sealing_temp_3": "",
"level_sensor_1": "",
"level_sensor_2": "",
"level_sensor_3": "",
"check_pack_1": "",
"check_pack_2": "",
"check_pack_3": "",
"comment": ""
}
and I would like to turn it to this structure and save
{
"category": "test",
"sealing_temp": "['a', 'b', 'c']",
"level_sensor": "['x', 'y', 'z']",
"check_pack": "[1, 2, 3]",
"comment": ""
}
Can someone guide me, I tried to use a for..in but got lost in the process
You could split the key and if it has digits at the end in it, then use it for an array to fill.
This proposal change the object and deletes unwanted properties which values are now in an array collected.
var object = { category: "test", sealing_temp_1: "s1", sealing_temp_2: "s2", sealing_temp_3: "s3", level_sensor_1: "l1", level_sensor_2: "l2", level_sensor_3: "l3", check_pack_1: "c1", check_pack_2: "c2", check_pack_3: "c3", comment: "cc" };
Object.keys(object).forEach(function (k) {
var parts = k.split(/_(?=\d+$)/);
if (parts.length === 2) {
object[parts[0]] = object[parts[0]] || [];
object[parts[0]][parts[1] - 1] = object[k]; // subtract one for zero based array
delete object[k];
}
});
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }