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);
Related
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");
}
}
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);
I have a JSON file that contains object like that:
{
"status": "ok",
"feed": {
},
"items": [
{
"title": "",
"author": ""
},
{
"title": "",
"author": ""
},
{
"title": "",
"author": ""
}
]
}
I want to loop through the items and get each item data like title and author.
The code I tried:
var json = $.getJSON({'url':"filejson" , 'async': false});
json = JSON.parse(json.responseText);
$.each(json, function(index , item) {
console.log(json[index]);
});
It would appear the sync version of it acts in a weird way,
var json = JSON.parse($.getJSON({'url':"filejson" , 'async': false}).responseText);
let items = json.items;
items.forEach(item=>{
console.log(item.title, item.author);
})
As a sidenote, you should really not be using async: false.
Object.keys(json).forEach(function(key) {
console.log(json[key])
})
// or if supported/polyfilled
Object.values(json).forEach(function(value) {
console.log(value)
})
Use map():
data.map(d => ({title: d.title, author: d.author}));
Please use the following code
var json = $.getJSON({'url':"filejson" , 'async': false});
json = JSON.parse(json.responseText);
$.each(json.items, function(key , value) {
console.log(value['title'] + " : "+ value['author']);
});
How can I declare a JavaScript object which can hold infinite amount of values like given below? I am new to Javascript.
var activities = [
{
subject: "",
genre :"",
username: "",
aboutuser: ""
},
{
subject: "",
genre :"",
username: "",
aboutuser: ""
},
{
subject: "",
genre :"",
username: "",
aboutuser: ""
},
...
]
Like this:
let myArray = []
myArray.push({
subject: "",
genre :"",
username: "",
aboutuser: ""
})
Just define an empty array and push the object into it as many times you need.
Here is my fiddle: DEMO
I want my JSON to be as below on click of "Save Actions" and when the category is "SMS". I'm not able to achieve this.
Also, the form fields change on change of category.
{
"name": "",
"category": "SMS",
"description": "",
"apiUrl": "",
"apiMethod": "GET",
"apiPayload": {
"senderName": "",
"number": "",
"message": ""
},
"#class": "action"
}
Any help would be much appreciated. Thanks :)
Move the apiPayload out of the reduce callback function.
And assign the value after the reduce loop.
$('#saveActions').on('click', function(e) {
var apiPayload = {};
var jsonData = $('form.form-horizontal#events')
.find(':input:not(button):not(#new-option-event)').get()
.reduce(function(acc, ele) {
if (ele.closest('.payload')) {
var i = 0;
apiPayload[ele.name] = ele.value.trim();
} else {
acc[ele.name] = ele.value.trim();
}
return acc;
}, {});
jsonData['apiPayload'] = apiPayload;//assign value
jsonData['#class'] = "action";
alert(JSON.stringify(jsonData, null, 4));
});