How to remove nested attributes? - javascript

I have this JSON file: http://danish-regional-data.googlecode.com/svn/trunk/danish_regional_data.json
How do I remove all the attribues within_5_km, within_10_km, within_25_km, within_50_km, within_100_km for all postcodes?
I have read this question: Remove a JSON attribute
$(document).ready(function() {
$.getJSON("post.json", function(data) {
var pc = data.postalcodes;
for (var id in pc) {
if(pc.hasOwnProperty(id)) {
for(var attr in pc[id]) {
if(pc[id].hasOwnProperty(attr) && attr.indexOf('within_') === 0) {
delete pc[id][attr];
}
}
}
}
$("#json").html(pc);
});
});

In ES2016 you can use destructing to pick the fields you want for the subset object.
//ES6 subset of an object by specific fields
var object_private = {name: "alex", age: 25, password: 123};
var {name,age} = object_private, object_public = {name,age}
//method 2 using literals
let object_public = (({name,age})=>({name,age}))(object_private);
//use map if array of objects
users_array.map(u=>u.id)

Go to the json url you provided and open the Firebug console. Then drop in the folloing code and execute it:
var p = document.getElementsByTagName('pre');
for(i=0; i < p.length; i++) {
var data = JSON.parse(p[i].innerHTML);
var pc = data.postalcodes;
// this is the code i gave you... the previous is jsut to pull it out of the page
// in Firebug - this works for me
for (var id in pc) {
if(pc.hasOwnProperty(id)) {
for(var attr in pc[id]) {
if(pc[id].hasOwnProperty(attr) && attr.indexOf('within_') === 0) {
console.log('Deleting postalcodes.'+id+'.'+attr);
delete pc[id][attr];
}
}
}
}
}
// assume data is the complete json
var pc = data.postalcodes;
for (var id in pc) {
if(pc.hasOwnProperty(id)) {
for(var attr in pc[id]) {
if(pc[id].hasOwnProperty(attr) && attr.indexOf('within_') === 0) {
delete pc[id][attr];
}
}
}
}

JSON truncated:
var data = {"postalcodes":
{"800":{"id":"800","name":"H\u00f8je Taastrup","region_ids":["1084"],"region_names":["Hovedstaden"],"commune_ids":["169"],"commune_names":["H\u00f8je-Taastrup"],"lat":"55.66713","lng":"12.27888", "within_5_km":["800","2620","2630","2633"],"within_10_km":["800","2600","2605","2620"]},
"900":{"id":"900","name":"K\u00f8benhavn C","region_ids":["1084"],"region_names":["Hovedstaden"],"commune_ids":["101"],"commune_names":["K\u00f8benhavns"],"lat":"55.68258093401054","lng":"12.603657245635986","within_5_km":["900","999"]},
"1417":{"commune_id":"390","region_id":"1085"}}};
var pc = data.postalcodes;
for (var id in pc) {
var entry = pc[id];
for(var attr in entry) {
if(attr.indexOf('within_') === 0) {
delete entry[attr];
}
}
}
console.dir(data); // your data object has been augmented at this point
you can also use regular expression
var data = {"postalcodes":
{"800":{"id":"800","name":"H\u00f8je Taastrup","region_ids":["1084"],"region_names":["Hovedstaden"],"commune_ids":["169"],"commune_names":["H\u00f8je-Taastrup"],"lat":"55.66713","lng":"12.27888", "within_5_km":["800","2620","2630","2633"],"within_10_km":["800","2600","2605","2620"]},
"900":{"id":"900","name":"K\u00f8benhavn C","region_ids":["1084"],"region_names":["Hovedstaden"],"commune_ids":["101"],"commune_names":["K\u00f8benhavns"],"lat":"55.68258093401054","lng":"12.603657245635986","within_5_km":["900","999"]},
"1417":{"commune_id":"390","region_id":"1085"}}};
var regexp = new RegExp("^within_", "i"); // case insensitive regex matching strings starting with within_
var pc = data.postalcodes;
for (var id in pc) {
var entry = pc[id];
for(var attr in entry) {
if(regexp.test(attr)) {
delete entry[attr];
}
}
}
console.dir(data);

I have written an npm module unset which exactly does this. You specify json paths similar to the json-path module until the leaf attribute that you want to remove.
let unset = require('unset');
let object = {a: { b: [ {x: 1}, {x: [{ e: 2} ]}]}};
let newObject = unset(object, ['/a/b[*]/x']);
Multiple paths are supported in the second argument

well you can do this:
var postalcodes = YOUR JSON;
for(var code in postalcodes)
{
delete postalcodes[code].within_5_km;
.
.
.
}
you will probably want to check if the code contains your properties...

Related

how do I check if a value is in a JSON return or not?

I'm writing a test in postman where I want to check if a JSON return contains the Label called 'RegressieMapTest'. This is my script:
pm.test("Is the folder created correctly?", function(){
var jsonData = pm.response.json();
var objString = JSON.stringify(jsonData);
var obj = JSON.parse(objString);
for (var i = 0; i < obj.Corsa.Data.length; i++){
if (obj.Corsa.Data[i].Label == "RegressieMapTest"){
console.log(obj.Corsa.Data[i].Label);
pm.expect(obj.Corsa.Data.Label).to.eql("RegressieMapTest");
}
}
pm.expect.fail();
})
But it doesn't quite work, every time I run this script it seems like it automatically jumps to pm.expect.fail() which is weird because 'RegressieMapTest' is inside the JSON return. Postman returns the following message:
Is the folder created correctly? | AssertionError: expect.fail()
pm.respose.json() is equalent to JSON.parse you don't have to do it again
also you can use array.find method instead of looping through it
pm.test("Is the folder created correctly?", function () {
var jsonData = pm.response.json();
pm.expect(obj.Corsa.Data.find(elem => elem.Label === "RegressieMapTest")).to.be.not.undefined
}
if array has any element with label RegressieMapTest then it will return that data elese returns undefined, so we are validating that it will not return undefined. Meaning it has the value
Your pm.expect.fail(); always runs. You want it to run only when you don't find the field. So just add a flag in your check block.
pm.test("Is the folder created correctly?", function(){
var jsonData = pm.response.json();
var objString = JSON.stringify(jsonData);
var obj = JSON.parse(objString);
var isFound = false;
for (var i = 0; i < obj.Corsa.Data.length; i++){
if (obj.Corsa.Data[i].Label == "RegressieMapTest"){
console.log(obj.Corsa.Data[i].Label);
pm.expect(obj.Corsa.Data.Label).to.eql("RegressieMapTest");
isFound = true;
}
}
if (!isFound) {
pm.expect.fail();
}
})

How to update JavaScript array dynamically

I have an empty javascript array(matrix) that I created to achieve refresh of divs. I created a function to dynamically put data in it. Then I created a function to update the Array (which I have issues).
The Data populated in the Array are data attributes that I put in a JSON file.
To better undertand, here are my data attributes which i put in json file:
var currentAge = $(this).data("age");
var currentDate = $(this).data("date");
var currentFullName = $(this).data("fullname");
var currentIDPerson = $(this).data("idPerson");
var currentGender = $(this).data("gender");
Creation of the array:
var arrayData = [];
Here is the function a created to initiate and addind element to the Array :
function initMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
var isFound = false;
// search if the unique index match the ID of the HTML one
for (var i = 0; i < arrayData.length; i++) {
if(arrayData[i].idPerson== p_currentIDPerson) {
isFound = true;
}
}
// If it doesn't exist we add elements
if(isFound == false) {
var tempArray = [
{
currentIDPerson: p_currentIDPerson,
currentGender: p_currentGender,
currentFullName: p_currentFullName,
currentDate: p_currentDate, currentAge: p_currentAge
}
];
arrayData.push(tempArray);
}
}
The update function here is what I tried, but it doesn't work, maybe I'm not coding it the right way. If you can help please.
function updateMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
for (var i = 0; i < arguments.length; i++) {
for (var key in arguments[i]) {
arrayData[i] = arguments[i][key];
}
}
}
To understand the '$this' and elm: elm is the clickableDivs where I put click event:
(function( $ ) {
// Plugin to manage clickable divs
$.fn.infoClickable = function() {
this.each(function() {
var elm = $( this );
//Call init function
initMatrixRefresh(elm.attr("idPerson"), elm.data("gender"), elm.data("fullname"), elm.data("date"), elm.data("age"));
//call function update
updateMatrix("idTest", "Alarme", "none", "10-02-17 08:20", 10);
// Définition de l'evenement click
elm.on("click", function(){});
});
}
$('.clickableDiv').infoClickable();
}( jQuery ));
Thank you in advance
Well... I would recommend you to use an object in which each key is a person id for keeping this list, instead of an array. This way you can write cleaner code that achieves the same results but with improved performance. For example:
var myDataCollection = {};
function initMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
if (!myDataCollection[p_currentIDPerson]) {
myDataCollection[p_currentIDPerson] = {
currentIDPerson: p_currentIDPerson,
currentGender: p_currentGender,
currentFullName: p_currentFullName,
currentDate: p_currentDate,
currentAge: p_currentAge
};
}
}
function updateMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
if (myDataCollection[p_currentIDPerson]) {
myDataCollection[p_currentIDPerson] = {
currentGender: p_currentGender,
currentFullName: p_currentFullName,
currentDate: p_currentDate,
currentAge: p_currentAge
};
}
}
Depending on your business logic, you can remove the if statements and keep only one function that adds the object when there is no object with the specified id and updates the object when there is one.
I think the shape of the resulting matrix is different than you think. Specifically, the matrix after init looks like [ [ {id, ...} ] ]. Your update function isn't looping enough. It seems like you are trying to create a data structure for storing and updating a list of users. I would recommend a flat list or an object indexed by userID since thats your lookup.
var userStorage = {}
// add/update users
userStorage[id] = {id:u_id};
// list of users
var users = Object.keys(users);

Check if an Object contains any value for the Same key in a Different Object JS

Sorry for the Lost Post . The problem statement
I have this URL -
http://www.XXXXX.com/mobiles-tablets/mobiles/apple?q=&idx=letsTango_default_products&p=0&hFR%5Bcategories.level0%5D%5B0%5D=Mobiles%20%26%20Tablets%20%2F%2F%2F%20Mobiles%20%2F%2F%2F%20Apple&nR%5Bprice.AED.default%5D%5B%3C%3D%5D%5B0%5D=2560&is_v=1
I had to extract all the query-params in a object like a key value pair .
and then check from a different object if any of these query-params with same key has any matching value .
This is my solution , I am new to java script and so i want to confirm if this is the right way to go about.
The solution so far works for all the cases . just let me know if the performance can be enhanced or any better way.
Fiddle Link for the Solution - http://jsfiddle.net/rahulsingh09/tqpzv/6/
code
var callingUrl = "http://www.letstango.com/mobiles-tablets/mobiles/apple?q=&idx=letsTango_default_products&fsrc=sort_price,brand&p=0&hFR%5Bcategories.level0%5D%5B0%5D=Mobiles%20%26%20Tablets%20%2F%2F%2F%20Mobiles%20%2F%2F%2F%20LG&nR%5Bprice.AED.default%5D%5B%3C%3D%5D%5B0%5D=2560&nR%5Bprice.AED.default%5D%5B%3E%3D%5D%5B0%5D=1138&is_v=1";
if (callingUrl) {
var queryParam = {};
var split = callingUrl.split("?");
if (split.length > 1) {
var query = split[1].split("&");
if (query.length > 1) {
_.each(query, function(q) {
var key = decodeURIComponent(q.split("=")[0]);
var value = decodeURIComponent(q.split("=")[1]);
if (value.indexOf(",") !== -1) {
value = value.split(",");
}
queryParam[key] = value;
})
}
}
}
if (!_.isEmpty(queryParam)) {
var value = {
"fsrc": ["brand"]
};
for (var key in value) {
if (value.hasOwnProperty(key)) {
for (var k in queryParam) {
if (queryParam.hasOwnProperty(k)) {
if (k === key) {
var index = _.intersection(value[key], queryParam[k]);
if (index.length > 0) {
console.log("Matches");
} else {
console.log("fails");
}
}
}
}
}
}
please note - the url can change depending upon the browser url.
Thanks in advance , I want to get the best performance possible for this problem.

how to change attribute text of json in jquery?

I am trying to change the property name /attr name of my json object.I try like that but nothing will change.I need to make json object after seen the input json and convert it like outjson
function changeData(data){
var title;
for(var i = 0; i < data.length; i++){
if(data[i].hasOwnProperty("displayName")){
data[i]["label"] = data[i]["displayName"];
delete data[i]["displayName"];
}
if(data[i].hasOwnProperty("displayDetail")){
data[i]["title"] = data[i]["displayDetail"];
delete data[i]["displayDetail"];
}
if(data[i].hasOwnProperty("inputType")){
if(data[i]["inputType"]=="NUMBER"){
data[i]["type"]="number"
}else if(data[i]["inputType"]=="TEXT"){
data[i]["type"]="text"
}else if(data[i]["inputType"]=="SWTICH"){
data[i]["type"]="select"
}
delete data[i]["inputType"];
}
}
console.log(data);
}
Try this - it's possibe to remove the if selection for inputType by creating a tiny lookup table from original value to new value:
function changeData(data) {
var map = { NUMBER: "number", TEXT: "text", SWITCH: "select" };
// data is an object - use for .. in to enumerate
for (var key in data.input) {
var e = data.input[key]; // alias for efficient structure dereferencing
e.label = e.displayName;
e.title = e.displayDetail;
e.type = map[e.inputType];
delete e.displayName;
delete e.displayDetail;
delete e.inputType;
}
};
There's really no need for the hasOwnProperty test these days - only use it if you think there's any risk that someone unsafely added to Object.prototype. jQuery manages without it quite happily, other modern code should do to.
If the mapping of field names was any longer I'd consider using another mapping table with another loop to remove the hard coded copy/delete pairs.
i have a nice Recursive function for that:
usage:
// replace list
var replacedObj = replaceAttrName(sourceObject, {foo: 'foooo', bar: 'baaar'});
so in your case you can easily do:
var newObj = replaceAttrName(json, {displayDetail: 'title', displayName: 'label', inputType: 'type'});
demo: http://jsfiddle.net/h1u0kq67/15/
the function is that:
function replaceAttrName(sourceObj, replaceList, destObj) {
destObj = destObj || {};
for(var prop in sourceObj) {
if(sourceObj.hasOwnProperty(prop)) {
if(typeof sourceObj[prop] === 'object') {
if(replaceList[prop]) {
var strName = replaceList[prop];
destObj[strName] = {};
replaceAttrName(sourceObj[prop], replaceList, destObj[strName]);
} else if(!replaceList[prop]) {
destObj[prop] = {};
replaceAttrName(sourceObj[prop], replaceList, destObj[prop]);
}
} else if (typeof sourceObj[prop] != 'object') {
if(replaceList[prop]) {
var strName = replaceList[prop];
destObj[strName] = sourceObj[prop];
} else if(!replaceList[prop]) {
destObj[prop] = sourceObj[prop];
}
}
}
}
return destObj;
}
If I am getting you right, you just want substitutions:
displayDetail => title
displayName => label
inputType => type.
I came up with the follwoing:
function changeData(data){
return JSON.parse(JSON.stringify(data).replace(/displayDetail/g, "title").replace(/displayName/g, "label").replace(/inputType/g, "type"));
}
Here is the Fiddle to play with.
Edit: I forgot replacements for "NUMBER", "TEXT" and "SWITCH".
function changeData(data){
return JSON.parse(JSON.stringify(data).replace(/displayDetail/g, "title").replace(/displayName/g, "label").replace(/inputType/g, "type").replace(/TEXT/g, "text").replace(/NUMBER/g, "number").replace(/SWITCH/g, "switch"));
}

Advanced search/queue array collection question

I have a pretty large number of objects "usrSession" I store them in my ArrayCollection usrSessionCollection.
I'M looking for a function that returns the latest userSessions added with a unique userID. So something like this:
1.
search the usrSessionCollection and only return one userSessions per userID.
2.
When it has returned x number of userSessions then deleted them from the usrSessionCollection
I'M stuck - would really love some code that can help me with that.
function ArrayCollection() {
var myArray = new Array;
return {
empty: function () {
myArray.splice(0, myArray.length);
},
add: function (myElement) {
myArray.push(myElement);
}
}
}
function usrSession(userID, cords, color) {
this.UserID = userID;
this.Cords = cords;
this.Color = color;
}
usrSessionCollection = new ArrayCollection();
$.getJSON(dataurl, function (data) {
for (var x = 0; x < data.length; x++) {
usrSessionCollection.add(new usrSession(data[x].usrID.toString(), data[x].usrcords.toString() ,data[x].color.toString());
}
});
Thanks.
The biggest issue is that you have made the array private to the outside world. Only methods through which the array can be interacted with are add and empty. To be able to search the array, you need to either add that functionality in the returned object, or expose the array. Here is a modified ArrayCollection:
function ArrayCollection() {
var myArray = new Array;
return {
empty: function () {
myArray.splice(0, myArray.length);
},
add: function (myElement) {
myArray.push(myElement);
},
getAll: function() {
return myArray;
}
}
}
Now to get the last N unique session objects in usrSessionCollection, traverse the sessions array backwards. Maintain a hash of all userID's seen so far, so if a repeated userID comes along, that can be ignored. Once you've collected N such user sessions or reached the beginning of the array, return all collected sessions.
usrSessionCollection.getLast = function(n) {
var sessions = this.getAll();
var uniqueSessions = [];
var addedUserIDs = {}, session, count, userID;
for(var i = sessions.length - 1; i >= 0, uniqueSessions.length < n; i--) {
session = sessions[i];
userID = session.userID;
if(!addedUserIDs[userID]) {
uniqueSessions.push(session);
addedUserIDs[userID] = true;
}
}
return uniqueSessions;
}
I wouldn't combine the delete step with the traversal step, just to keep things simple. So here's the remove method that removes the given session from the array. Again, it's better to modify the interface returned by ArrayCollection rather than tampering with the sessions array directly.
function ArrayCollection(..) {
return {
..,
remove: function(item) {
for(var i = 0; i < myArray.length; i++) {
if(item == myArray[i]) {
return myArray.splice(i, 1);
}
}
return null;
}
};
}
Example: Get the last 10 unique sessions and delete them:
var sessions = usrSessionCollection.getLast(10);
for(var i = 0; i < sessions.length; i++) {
console.log(sessions[i].UserID); // don't need dummy variable, log directly
usrSessionCollection.remove(sessions[i]);
}
See a working example.
You made your array private, so you can't access the data, except adding a new element or removing them all. You need to make the array public, or provide a public interface to access the data. Like first(), next() or item(index).
Then you can add a search(userID) method to the usrSessionCollection, which uses this interface to go through the elements and search by userID.
UPDATE: this is how I would do it: - See it in action. (click preview)
// user session
function userSession(userID, cords, color) {
this.UserID = userID;
this.Cords = cords;
this.Color = color;
}
// a collection of user sessionions
// a decorated array basically, with
// tons of great methods available
var userSessionCollection = Array;
userSessionCollection.prototype.lastById = function( userID ) {
for ( var i = this.length; i--; ) {
if ( this[i].UserID === userID ) {
return this[i];
}
}
// NOTE: returns undefined by default
// which is good. means: no match
};
// we can have aliases for basic functions
userSessionCollection.prototype.add = Array.prototype.push;
// or make new ones
userSessionCollection.prototype.empty = function() {
return this.splice(0, this.length);
};
//////////////////////////////////////////////////////
// make a new collection
var coll = new userSessionCollection();
// put elements in (push and add are also available)
coll.add ( new userSession(134, [112, 443], "#fffff") );
coll.push( new userSession(23, [32, -32], "#fe233") );
coll.push( new userSession(324, [1, 53], "#ddddd") );
// search by id (custom method)
var search = coll.lastById(134);
if( search ) {
console.log(search.UserID);
} else {
console.log("there is no match");
}
// empty and search again
coll.empty();
search = coll.lastById(134);
if( search ) {
console.log(search.UserID);
} else {
console.log("there is no match");
}

Categories

Resources