Remove key/value pairs in JSON using javascript - javascript

I have JSON that looks like this:
{
"primary": {
"value": "#0093c1",
"type": "color"
},
"background": {
"value": "#f2f2f2",
"type": "color"
},
"foreground": {
"value": "#000000",
"type": "color"
},
"secondary": {
"value": "#32c100",
"type": "color"
},
"alert": {
"value": "#c10000",
"type": "color"
}
}
How do I first check if each has a type and if so, then remove all type key/value pairs no matter how nested they might be?

try this
Object.keys(obj).forEach((prop) => {
delete obj[prop].type;
});
result
{
"primary": {
"value": "#0093c1"
},
"background": {
"value": "#f2f2f2"
},
"foreground": {
"value": "#000000"
},
"secondary": {
"value": "#32c100"
},
"alert": {
"value": "#c10000"
}
}

Related

how to sort an array in comparison to another array

let selected_variation = [{
"type": "Capacity",
"value": "512G",
},
{
"type": "Color",
"value": "#000000",
}
]
let attributes = [{
"id": "Color",
"name": "Color",
"type": "swatch",
"items": [{
"displayValue": "Green",
"value": "#44FF03",
"id": "Green"
},
{
"displayValue": "Cyan",
"value": "#03FFF7",
"id": "Cyan"
},
{
"displayValue": "Blue",
"value": "#030BFF",
"id": "Blue"
},
{
"displayValue": "Black",
"value": "#000000",
"id": "Black"
},
{
"displayValue": "White",
"value": "#FFFFFF",
"id": "White"
}
]
},
{
"id": "Capacity",
"name": "Capacity",
"type": "text",
"items": [{
"displayValue": "512G",
"value": "512G",
"id": "512G"
},
{
"displayValue": "1T",
"value": "1T",
"id": "1T"
}
]
}
]
so I have these two arrays one I am creating to track the selected variation of the product from the user there is a bug in it the order of the variation in my created array depends on which order the user clicks on the input fields I need to map my array in the order of the resulted api and the variations are not fixed it actually varies according to the product so my expected output
Output
let selected_variation = [
{"type":"Color","value":"#000000"},
{"type":"Capacity","value":"512G"}
]
the same order the API is following
Maybe you could try this:
const order = attributes.map((attribute) =>
selected_variation.find((v) => v.type === attribute.id)
);
console.log(order)
Based on accepted answer of this question: Javascript - sort array based on another array
const selected_variation = [{
"type": "Capacity",
"value": "512G",
},
{
"type": "Color",
"value": "#000000",
}
]
const attributes = [{
"id": "Color",
"name": "Color",
"type": "swatch",
"items": [{
"displayValue": "Green",
"value": "#44FF03",
"id": "Green"
},
{
"displayValue": "Cyan",
"value": "#03FFF7",
"id": "Cyan"
},
{
"displayValue": "Blue",
"value": "#030BFF",
"id": "Blue"
},
{
"displayValue": "Black",
"value": "#000000",
"id": "Black"
},
{
"displayValue": "White",
"value": "#FFFFFF",
"id": "White"
}
]
},
{
"id": "Capacity",
"name": "Capacity",
"type": "text",
"items": [{
"displayValue": "512G",
"value": "512G",
"id": "512G"
},
{
"displayValue": "1T",
"value": "1T",
"id": "1T"
}
]
}
]
selected_variation.sort((a, b) => {
return attributes.findIndex(attr => attr.id === a.type) - attributes.findIndex(attr => attr.id === b.type);
});
console.log(selected_variation);
But it will work really long if there will be a lot of elements because we must to loop through attributes array twice for each pair again and again. But if we will use a little more memory we can greatly optimize the algorithm. The main idea is to create a dictionary where the keys are ids of attributes and values are they index in attributes array:
const selected_variation = [{
"type": "Capacity",
"value": "512G",
},
{
"type": "Color",
"value": "#000000",
}
]
const attributes = [{
"id": "Color",
"name": "Color",
"type": "swatch",
"items": [{
"displayValue": "Green",
"value": "#44FF03",
"id": "Green"
},
{
"displayValue": "Cyan",
"value": "#03FFF7",
"id": "Cyan"
},
{
"displayValue": "Blue",
"value": "#030BFF",
"id": "Blue"
},
{
"displayValue": "Black",
"value": "#000000",
"id": "Black"
},
{
"displayValue": "White",
"value": "#FFFFFF",
"id": "White"
}
]
},
{
"id": "Capacity",
"name": "Capacity",
"type": "text",
"items": [{
"displayValue": "512G",
"value": "512G",
"id": "512G"
},
{
"displayValue": "1T",
"value": "1T",
"id": "1T"
}
]
}
]
const attributesMap = new Map();
attributes.forEach((attribute, index) => attributesMap.set(attribute.id, index))
selected_variation.sort((a, b) => attributesMap.get(a.type) - attributesMap.get(b.type));
console.log(selected_variation);

How to get the absolute path from object using a recursive function?

I am converting the object to tree node format using the below method
function getNodes(object) {
return Object
.entries(object)
.map(([key, value]) => value && typeof value === 'object' ?
{
value: key + value,
label: key,
children: getNodes(value)
} :
{
value: key + value,
label: key
}
);
}
The sample object is:
var object = {
"income-array": [{
"income": {
"id": "1234",
"currency": "dollar",
"details": {
"individual-income": [{
"name": "abcd",
"income": 100
}, {
"name": "xyz",
"income": 500
}]
}
}
}]
}
I am getting this result:
[{
"value": "income-array[object Object]",
"label": "income-array",
"children": [{
"value": "0[object Object]",
"label": "0",
"children": [{
"value": "income[object Object]",
"label": "income",
"children": [{
"value": "id1234",
"label": "id"
}, {
"value": "currencydollar",
"label": "currency"
}, {
"value": "details[object Object]",
"label": "details",
"children": [{
"value": "individual-income[object Object],[object Object]",
"label": "individual-income",
"children": [{
"value": "0[object Object]",
"label": "0",
"children": [{
"value": "nameabcd",
"label": "name"
}, {
"value": "income100",
"label": "income"
}]
}, {
"value": "1[object Object]",
"label": "1",
"children": [{
"value": "namexyz",
"label": "name"
}, {
"value": "income500",
"label": "income"
}]
}]
}]
}]
}]
}]
}]
I want to get the value property path from root to a particular node like the below. I am confused with how to append step by step path to value.
[{
"value": "income-array",
"label": "income-array",
"children": [{
"value": "['income-array'][0]",
"label": "0",
"children": [{
"value": "['income-array'][0]['income']",
"label": "income",
"children": [{
"value": "['income-array'][0]['income']['id']",
"label": "id"
}, {
"value": "['income-array'][0]['income']['currencydollar']",
"label": "currency"
}, {
"value": "['income-array'][0]['income']['details']",
"label": "details",
"children": [{
"value": "['income-array'][0]['income']['details']['individual-income']",
"label": "individual-income",
"children": [{
"value": "['income-array'][0]['income']['details']['individual-income'][0]",
"label": "0",
"children": [{
"value": "['income-array'][0]['income']['details']['individual-income'][0]['name']",
"label": "name"
}, {
"value": "['income-array'][0]['income']['details']['individual-income'][0]['income']",
"label": "income"
}]
}, {
"value": "['income-array'][0]['income']['details']['individual-income'][1]",
"label": "1",
"children": [{
"value": "['income-array'][0]['income']['details']['individual-income'][1]['name']",
"label": "name"
}, {
"value": "['income-array'][0]['income']['details']['individual-income'][1]['income']",
"label": "income"
}]
}]
}]
}]
}]
}]
}]
Can you please guide me how to resolve this? Thanks
The outer function needs to pass its own current absolute path (which is value in your code) to the inner function,
in order to let the inner function know the previous paths.
Notice the parentPath='' parameter and children: getNodes(value, currentPath) below
function getNodes(object, parentPath = "") {
return Object.entries(object).map(([key, value]) => {
const currentPath = parentPath + `[${key}]`;
return value && typeof value === "object"
? {
value: currentPath,
label: key,
children: getNodes(value, currentPath),
}
: {
value: currentPath,
label: key,
};
});
}
After that, run getNodes(object) in the browser and you will get a result like this.
[
{
"value": "[income-array]",
"label": "income-array",
"children": [
{
"value": "[income-array][0]",
"label": "0",
"children": [
{
"value": "[income-array][0][income]",
"label": "income",
"children": [
{
"value": "[income-array][0][income][id]",
"label": "id"
},
{
"value": "[income-array][0][income][currency]",
"label": "currency"
},
{
"value": "[income-array][0][income][details]",
"label": "details",
"children": [
{
"value": "[income-array][0][income][details][individual-income]",
"label": "individual-income",
"children": [
{
"value": "[income-array][0][income][details][individual-income][0]",
"label": "0",
"children": [
{
"value": "[income-array][0][income][details][individual-income][0][name]",
"label": "name"
},
{
"value": "[income-array][0][income][details][individual-income][0][income]",
"label": "income"
}
]
},
{
"value": "[income-array][0][income][details][individual-income][1]",
"label": "1",
"children": [
{
"value": "[income-array][0][income][details][individual-income][1][name]",
"label": "name"
},
{
"value": "[income-array][0][income][details][individual-income][1][income]",
"label": "income"
}
]
}
]
}
]
}
]
}
]
}
]
}
]

Check if the nested object contains a specific key, then replace a key of the parent object

I've a nested object.
Now, I need to check if the object contains 'items' as a key anywhere which is an 'array' always, then replace 'type' : 'list' by 'type': 'array' of the parent.
It works well for the 1st level but when it comes to the nested object which contains 'items' again, I'm stuck.
function convertData() {
const arr = {
"type": "list",
"items": [{
"type": "list",
"items": [{
"type": "string",
"value": 0,
"unit": "",
"pattern": "^(auto|0)$|^[+-]?[0-9]+(\\.)?([0-9]+)?(rem|px|em|ex|%|in|cm|mm|pt|pc)$"
}, {
"type": "string",
"value": 0.1875,
"unit": "rem",
"pattern": "^(auto|0)$|^[+-]?[0-9]+(\\.)?([0-9]+)?(rem|px|em|ex|%|in|cm|mm|pt|pc)$"
}, {
"type": "string",
"value": 0.75,
"unit": "rem",
"pattern": "^(auto|0)$|^[+-]?[0-9]+(\\.)?([0-9]+)?(rem|px|em|ex|%|in|cm|mm|pt|pc)$"
}, {
"type": "string",
"value": 0,
"unit": "",
"pattern": "^(auto|0)$|^[+-]?[0-9]+(\\.)?([0-9]+)?(rem|px|em|ex|%|in|cm|mm|pt|pc)$"
}]
}, {
"type": "string",
"value": {
"r": 161,
"g": 161,
"b": 161,
"a": 0.75,
"hex": "#a1a1a1"
},
"pattern": "^rgba?\\(((25[0-5]|2[0-4]\\d|1\\d{1,2}|\\d\\d?)\\s*,\\s*?){2}(25[0-5]|2[0-4]\\d|1\\d{1,2}|\\d\\d?)\\s*,?\\s*([01]\\.?\\d*?)?\\)"
}]
};
if (Array.isArray(arr.items)) {
arr.type = "array";
console.log(arr);
}
}
<button onclick="convertData()">Click me!</button>
You can do that using recursion.
Create a function changeValue which takes an object as argument.
Check the object has key items using Object.hasOwnProperty()
If it contains change the type to "array" and call the function recursively on its each item.
function convertData() {
const arr = { "type": "list", "items": [{ "type": "list", "items": [{ "type": "string", "value": 0, "unit": "", "pattern": "^(auto|0)$|^[+-]?[0-9]+(\\.)?([0-9]+)?(rem|px|em|ex|%|in|cm|mm|pt|pc)$" }, { "type": "string", "value": 0.1875, "unit": "rem", "pattern": "^(auto|0)$|^[+-]?[0-9]+(\\.)?([0-9]+)?(rem|px|em|ex|%|in|cm|mm|pt|pc)$" }, { "type": "string", "value": 0.75, "unit": "rem", "pattern": "^(auto|0)$|^[+-]?[0-9]+(\\.)?([0-9]+)?(rem|px|em|ex|%|in|cm|mm|pt|pc)$" }, { "type": "string", "value": 0, "unit": "", "pattern": "^(auto|0)$|^[+-]?[0-9]+(\\.)?([0-9]+)?(rem|px|em|ex|%|in|cm|mm|pt|pc)$" }] }, { "type": "string", "value": { "r": 161, "g": 161, "b": 161, "a": 0.75, "hex": "#a1a1a1" }, "pattern": "^rgba?\\(((25[0-5]|2[0-4]\\d|1\\d{1,2}|\\d\\d?)\\s*,\\s*?){2}(25[0-5]|2[0-4]\\d|1\\d{1,2}|\\d\\d?)\\s*,?\\s*([01]\\.?\\d*?)?\\)" }] };
changeValue(arr);
console.log(arr)
}
function changeValue(obj){
if(obj.hasOwnProperty('items')){
obj.type = "array";
obj.items.forEach(x => changeValue(x))
}
}
<button onclick="convertData()">Click me!</button>

Nested Loops in angularjs

I have been using nested loops to access data of the json object to display the id and type of topping, however its not working. Here's my code:
var j_obj = {
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters": {
"batter": [{
"id": "1001",
"type": "Regular"
}, {
"id": "1002",
"type": "Chocolate"
}, {
"id": "1003",
"type": "Blueberry"
}, {
"id": "1004",
"type": "Devil's Food"
}]
},
"topping": [{
"id": "5001",
"type": "None"
}, {
"id": "5002",
"type": "Glazed"
}, {
"id": "5005",
"type": "Sugar"
}, {
"id": "5007",
"type": "Powdered Sugar"
}, {
"id": "5006",
"type": "Chocolate with Sprinkles"
}, {
"id": "5003",
"type": "Chocolate"
}, {
"id": "5004",
"type": "Maple"
}]
}
var Outer_log=[];
debugger
angular.forEach(j_obj, function(an_object){
//Outer_log.push("ID : "+an_object.id+" type : "+an_object.type);
angular.forEach(an_object.topping,function(innerobject){
Outer_log.push("ID : "+innerobject.id+" type : "+innerobject.type);
},Outer_log);
});
console.log(Outer_log);
Could someone please highlight the error in above code, Thanks
Without using nested loop you can iterate using angular.forEach like this
var finalArray=[];
angular.forEach(j_obj[0].topping, function(eachobject){
finalArray.push("ID : "+ eachobject.id+" type : "+ eachobject.type);
});
Angulars forEach is intended to iterate over arrays not object. so if you change your code to something like this
var j_obj = [{ ...}] //object is wrapped inside array.
it will work. Another thing is you don't need a nested loop in this case. You can just do:
angular.forEach(j_obj.topping, function(key, value){ ... });
you are iterating over object where as loop run over array.
hope this helps JSfiddle link
var j_obj = [{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters": {
"batter": [{
"id": "1001",
"type": "Regular"
}, {
"id": "1002",
"type": "Chocolate"
}, {
"id": "1003",
"type": "Blueberry"
}, {
"id": "1004",
"type": "Devil's Food"
}]
},
"topping": [{
"id": "5001",
"type": "None"
}, {
"id": "5002",
"type": "Glazed"
}, {
"id": "5005",
"type": "Sugar"
}, {
"id": "5007",
"type": "Powdered Sugar"
}, {
"id": "5006",
"type": "Chocolate with Sprinkles"
}, {
"id": "5003",
"type": "Chocolate"
}, {
"id": "5004",
"type": "Maple"
}]
}]
var Outer_log = [];
angular.forEach(j_obj, function(an_object) {
//Outer_log.push("ID : "+an_object.id+" type : "+an_object.type);
angular.forEach(an_object.topping, function(innerobject) {
Outer_log.push("ID : " + innerobject.id + " type : " + innerobject.type);
}, Outer_log);
});
console.log(Outer_log);

Wait for d3 to load

I am creating a pie chart using d3 to load a pie chart -
var pie = new d3pie(
// pie control Json
);
This is working great however I am looking to do logic after the pie has fully rendered.
I have tried to use the when done logic (like when doing an ajax call) like so -
$.when(pie).done(function () {
// further logic to be completed after pie has loaded
});
However this does not work in that it just steps into the when clause even tho the pie has not loaded fully. How can I do this?
You are looking for the onload callback:
callbacks: {
onload: function(){
console.log('chart is loaded!');
}
}
Full code sample:
<html>
<head></head>
<body>
<div id="pieChart"></div>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.4/d3.min.js"></script>
<script src="https://rawgit.com/benkeen/d3pie/master/d3pie/d3pie.min.js"></script>
<script>
var pie = new d3pie("pieChart", {
"header": {
"title": {
"text": "Lots of Programming Languages",
"fontSize": 24,
"font": "open sans"
},
"subtitle": {
"text": "A full pie chart to show off label collision detection and resolution.",
"color": "#999999",
"fontSize": 12,
"font": "open sans"
},
"titleSubtitlePadding": 9
},
"footer": {
"color": "#999999",
"fontSize": 10,
"font": "open sans",
"location": "bottom-left"
},
"size": {
"canvasWidth": 590,
"pieOuterRadius": "90%"
},
"data": {
"sortOrder": "value-desc",
"content": [
{
"label": "JavaScript",
"value": 264131,
"color": "#2484c1"
},
{
"label": "Ruby",
"value": 218812,
"color": "#0c6197"
},
{
"label": "Java",
"value": 157618,
"color": "#4daa4b"
},
{
"label": "PHP",
"value": 114384,
"color": "#90c469"
},
{
"label": "Python",
"value": 95002,
"color": "#daca61"
},
{
"label": "C+",
"value": 78327,
"color": "#e4a14b"
},
{
"label": "C",
"value": 67706,
"color": "#e98125"
},
{
"label": "Objective-C",
"value": 36344,
"color": "#cb2121"
},
{
"label": "Shell",
"value": 28561,
"color": "#830909"
},
{
"label": "Cobol",
"value": 24131,
"color": "#923e99"
},
{
"label": "C#",
"value": 100,
"color": "#ae83d5"
},
{
"label": "Coldfusion",
"value": 68,
"color": "#bf273e"
},
{
"label": "Fortran",
"value": 218812,
"color": "#ce2aeb"
},
{
"label": "Coffeescript",
"value": 157618,
"color": "#bca44a"
},
{
"label": "Node",
"value": 114384,
"color": "#618d1b"
},
{
"label": "Basic",
"value": 95002,
"color": "#1ee67b"
},
{
"label": "Cola",
"value": 36344,
"color": "#b0ec44"
},
{
"label": "Perl",
"value": 32170,
"color": "#a4a0c9"
},
{
"label": "Dart",
"value": 28561,
"color": "#322849"
},
{
"label": "Go",
"value": 264131,
"color": "#86f71a"
},
{
"label": "Groovy",
"value": 218812,
"color": "#d1c87f"
},
{
"label": "Processing",
"value": 157618,
"color": "#7d9058"
},
{
"label": "Smalltalk",
"value": 114384,
"color": "#44b9b0"
},
{
"label": "Scala",
"value": 95002,
"color": "#7c37c0"
},
{
"label": "Visual Basic",
"value": 78327,
"color": "#cc9fb1"
},
{
"label": "Scheme",
"value": 67706,
"color": "#e65414"
},
{
"label": "Rust",
"value": 36344,
"color": "#8b6834"
},
{
"label": "FoxPro",
"value": 32170,
"color": "#248838"
}
]
},
"labels": {
"outer": {
"pieDistance": 32
},
"inner": {
"hideWhenLessThanPercentage": 3
},
"mainLabel": {
"fontSize": 11
},
"percentage": {
"color": "#ffffff",
"decimalPlaces": 0
},
"value": {
"color": "#adadad",
"fontSize": 11
},
"lines": {
"enabled": true
},
"truncation": {
"enabled": true
}
},
"effects": {
"pullOutSegmentOnClick": {
"effect": "linear",
"speed": 400,
"size": 8
}
},
"misc": {
"gradient": {
"enabled": true,
"percentage": 100
}
},
callbacks: {
onload: function(){
console.log('chart is loaded!');
}
}
});
</script>
</body>
</html>

Categories