How to remove null values from javascript object - javascript

I have a javascript object that contains two arrays. Sometimes one of the arrays may be empty. I'm trying to loop through the object via a recursive function but I don't want any arrays that are empty or empty strings to enter the loop. What I have so far is producing the error Typeerror: obj.filter is not a function.
NOTE: obj is in this example has two arrays inside of it, but really, it could be anything that I pass into the function.
var obj = {
selected: [ "value1", "value"2],
unselected: []
}
function clearAndSetSelectElement($elem, obj, isEmpty) {
if(isEmpty) $elem.empty(); //empty the select element if it isn't empty
$.each(obj.filter(function(v){return v != null}), function() { //filter out empty arrays or empty strings
if(this instanceof Array) clearAndSetSelectElement($elem, this, false); //if this is an array make recursive call
$elem.append("<option />").val(this).text(this)); //append value to select element
});
}

obj.filter is not a function, but obj.selected.filter should be (obj is an object, not an array).
It won't work in IE7 by default I guess, you'll either have to copy the polyfill from Mozilla Developer's Network (MDN) or use Modernizr.

May be you can try this (if you want to populate a select with some options from an array)
HTML
<select id="sel"></select>​
JS
function setSelect(elem, obj)
{
for(var o in obj)
{
if(obj[o] instanceof Array && obj[o].length)
{
$.each(obj[o], function(key, value) {
elem.append($("<option></option>").attr("value",value).text(value));
});
}
}
}
Populate the selct using setSelect function
var obj = {
selected: [ "value1", "value2"],
unselected: []
}
var elem=$('#sel');
setSelect(elem, obj);
DEMO.

Related

Search value in object

I have following object im not sure how to proceed.
Object image
How can I go through all objects and select the content array and search for a value x. And when the value x is in the object I need to get the object title from the object where the value was found.
Can anyone give me a hint how I can solve this problem?
you can use for...in to iterate over the object and indexOf() to check if a key exists in the array content. something like this:
function searchVal(x){
for(var key in obj){
if(obj[key].hasOwnProperty('content') && obj[key].content.includes(x))
return key;
}
}
You can use for...in to iterate the object keys, then a regular for loop to check the content array for your specific value:
function findTitle(x) {
for (var key in obj) {
for (var i = 0; i < obj[key].content.length; i++) {
if (obj[key].content[i] === x) {
return key;
}
}
}
}
let name = Object.values( obj /*your main object*/ )
.find( obj => obj.content.includes(x) )
.name;
You could find the first object in the Objects values of your main obj, that has a property content which includes x, then get the name of that object.

Find index of object in array by key

I have an array of objects like so
myobj= [{"item1" : info in here},{"item2" : info in here}, {"item3" : info in here}]
I'm trying to modify one, but I only know its key. I need to pinpoint the item1 object so I can change its value (the values are random and I don't know them, so I can't rely upon them).
If I could just get the index of the item it would be pretty easy: myobj[index].value = "newvalue".
Maybe using the index isn't the best way, so if it isn't, I'm open to other ideas.
I was thinking I could try something like
myobj.objectVar
Where objectVar is the key I'm being passed (item1, for example), however this does not work, possibly because it's a variable? Is it possible to use a variable like this maybe?
If it helps, I'm using underscore.js as well.
Your guess at a solution doesn't work because you're not accessing the individual objects, you're accessing an array of objects, each of which has a single property.
To use the data in the format you've got now, you need to iterate over the outer array until you find the object that contains the key you're after, and then modify its value.
myobj= [{"item1" : info in here},{"item2" : info in here}, {"item3" : info in here}]
function setByKey(key, value) {
myObj.forEach(function (obj) {
// only works if your object's values are truthy
if (obj[key]) {
obj[key] = value;
}
});
}
setByKey('item1', 'new value');
Of course, the far better solution is to stop using an array of single-property objects, and just use one object with multiple properties:
myobj= {"item1" : info in here, "item2" : info in here, "item3" : info in here};
Now, you can simply use myObject.item1 = "some new value" and it will work fine.
You can write a function like,
function getElementsHavingKey(key) {
var objectsHavingGivenKey = [];
//loop through all the objects in the array 'myobj'
myobj.forEach(function(individualObject) {
//you can use 'hasOwnProperty' method to find whether the provided key
// is present in the object or not
if(individualObject.hasOwnProperty(key)) {
// if the key is present, store the object having the key
// into the array (many objects may have same key in it)
objectsHavingGivenKey.push(individualObject);
}
});
// return the array containing the objects having the keys
return objectsHavingGivenKey;
}
If you only want to get the index of elements having the given key
You can do something like this,
function getIndexesOfElementsHavingKey(key) {
var objectsHavingGivenKey = [];
//loop through all the objects in the array 'myobj'
myobj.forEach(function(individualObject, index) {
//you can use 'hasOwnProperty' method to find whether the provided key
// is present in the object or not
if(individualObject.hasOwnProperty(key)) {
//push index of element which has the key
objectsHavingGivenKey.push(index);
}
});
// returns the array of element indexes which has the key
return objectsHavingGivenKey;
}
Try this code:
function changeObj( obj, key, newval )
{
for( var i=0, l=obj.length; i<j; i++)
{
if( key in obj[i] )
{
obj[i] = newval;
return;
}
}
}
var myObjArray= [{"item1" : "info in here"},{"item2" : "info in here"}, {"item3" : "info in here"}]
To find and add new value to the object inside an array:
myObjArray.forEach(function(obj) {
for(var key in obj) {
// in case you're matching key & value
if(key === "item1") {
obj[key] = "update value";
// you can even set new property as well
obj.newkey = "New value";
}
}
});
You can access objects the same using their index, even the object inside the original object.
Is this kind of what your looking for:
var otherObj = [{"oitem":"oValue"}];
var myobj= [{"item1" : otherObj},{"item2" : "2"}, {"item3" : "tesT"}];
myobj[0].item1[0].oitem = "newvalue";
alert(myobj[0].item1[0].oitem);

Javascript: Determine if all of the elements in the array are keys in the object

I am trying to figure out if all of the elements in an array are keys in the object.
var obj = { name: 'Computer', cost: '$1,000' };
var myArray = [ 'name', 'cost', 'bio' ]; //another example would be var myArray = [];
for(var x = 0; x < myArray.length; x++){
if (myArray[x] in obj)
{
return true;
}
}
How can I check if all of the elements in an array are keys in the object?
Do it the other way around. If you find someone in the array who is NOT in the object then you return false. If you reach the end of the loop then you return true because all the keys were in the object.
Depending on what you want, this might do the trick:
function hasKeys(obj, keys) {
for (var i=0; i != keys.length; ++i) {
if (!(keys[i] in obj))
return false;
}
return true;
};
One subtlety you need to ask yourself: do you want to know if the object has the keys directly (i.e. not somewhere in its prototype stack?) If so, then replace keys[i] in obj with obj.hasOwnProperty(keys[i])
function hasKeys(obj, keys) {
return keys.every(Object.prototype.hasOwnProperty.bind(obj));
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every states, "The every method executes the provided callback function once for each element present in the array until it finds one where callback returns a falsy value (a value that becomes false when converted to a Boolean). If such an element is found, the every method immediately returns false. Otherwise, if callback returned a true value for all elements, every will return true. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values" (emphasis mine).
Array.some() makes for a clean solution.
// object in question
var obj = { ... };
// keys that need to be present in the object
var keys = [ ... ];
// iterate through the whitelist until we find a key that doesn't exist in the object. If all exist, that means Array.some() is false.
var valid = !keys.some(function(key) {
return !obj.hasOwnProperty(key);
});
An alternative solution would be using a similar concept, but with Array.every(). It is to note that this will generally be slower because it always has to touch every element in the whitelist.
// iterate through the whitelist, making sure the object has each key.
var valid = keys.every(obj.hasOwnProperty);
This problem can be expressed in terms of set inclusion: does the set of property keys completely include the array of required keys? So we can write it as
includes(Object.keys(obj), arr)
So now we just need to write includes.
function includes(arr1, arr2) {
return arr2.every(function(key) {
return contains(arr1, key);
}
}
For contains, we could use Underscore's _.contains, or just write it ourselves:
function contains(arr, val) {
return arr.indexOf(val) !== -1;
}
If we are interested in conciseness at the possible expense of readability, we could shorten our definition of includes to use Function#bind instead of the anonymous function:
function includes(arr1, arr2) {
return arr2.every(contains.bind(0, arr1));
}
Now we have functions we can use for other things, instead of mixing up the two different aspects of the problem--the keys of an object, and set inclusion. If we really want to write an all-in-one function, it becomes the somewhat more readable:
function hasMany(obj, arr) {
return arr.every(_.contains.bind(0, Object.keys(obj));
}
If we want more readability, like we were writing a novel:
function object_has_required_keys(object, required_keys) {
var object_keys = Object.keys(object);
function key_is_present(key) {
return object_keys.indexOf(key) !== -1;
}
return required_keys.every(key_is_present);
}
Underscore's _.intersection
If we're lazy (or smart), we could use Underscore's _.intersection to implement includes:
function includes(arr1, arr2) {
return _.intersection(arr1, arr2).length === arr2.length;
}
The idea is to take the intersection, and if the first array includes the second entirely, then the intersection will contain all the elements of the second array, which we can check by comparing their lengths.
Using ES6 sets
Thinking ahead to ES6, we could implement include using its sets, which ought to be faster:
function includes(arr1, arr2) {
var set = new Set(arr1);
return arr2.every(Set.prototype.has.bind(set));
}

How to delete particular nested json attribute

I want to delete __metadata where ever it appears .How to do that I searched this question but didn't get exact solution. hope you will help me out .
{
"__metadata":{
"uri":"asd",
"type":"DP_CART_SRV.DPCARTHeader"
},
"Dealer":{
"__metadata":{
"uri":"asd"
},
"CustomerNo":"",
"Name1":"",
"Name2":""
},
"Retailer":{
"__metadata":{
"uri":"asd"
},
"CustomerNo":"",
"Name1":"",
"Name2":""
},
"Cart":"0000000081",
"Type":"SH",
"CreatedOn":"/Date(1399420800000)/",
"ChangedOn":null,
"OrderId":"",
"OrderType":"",
"ReqDeliveryDate":"2014/05/31",
"OrderValue":"11.00",
"DocCurrency":"EUR",
"NetValue":"11.00",
"Freight":"0.00",
"Discount":"0.00",
"Tax":"0.00",
"Remarks":"Remarks",
"Items":{
"results":[
{
"__metadata":{
"uri":"asd"
},
"Cart":"0000000081",
"ItemNo":"000010",
"ProductID":"FAN_FG1",
"ItemDesc":"Finshed product FAN",
"Quantity":"1.000",
"Uom":"KAR",
"Price":"11.00",
"Currency":"EUR",
"Available":"",
"DeleteStatus":""
},
{
"__metadata":{
"uri":"",
"type":""
},
"DeleteStatus":"",
"Available":"",
"Currency":"",
"Price":"",
"Uom":"",
"Quantity":"",
"ItemDesc":"",
"ProductID":"",
"ItemNo":"",
"Cart":""
}
]
}
}
Here is a fun one. Not very obvious way how you can do it:
var result = JSON.parse(JSON.stringify(obj, function(key, value) {
return key !== '__metadata' ? value : undefined;
}));
It makes use of the replacer function JSON.stringify method accepts:
replacer
If a function, transforms values and properties encountered while stringifying; if an array, specifies the set of properties included in objects in the final string.
A detailed description of the replacer function is provided in the javaScript guide article Using native JSON.
However be aware that this is not intended JSON.stringify and JSON.parse usage. Also of course the result will no longer be the original object, but a new object.
Demo: http://jsfiddle.net/7Gj47/
I don't really know what you mean by "nested json attribute". The OP appears to be an object literal, which is the syntax used for JSON, however JSON is a string.
Anyhow, supposing you have JSON, it can be turned into an object using JSON.parse. You can then iterate over the object and remove any property with a certain name, and recursively remove properties from "nested" objects using a function like:
function removeProp(obj, propName) {
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
if (p == propName) {
delete obj[p];
} else if (typeof obj[p] == 'object') {
removeProp(obj[p], propName);
}
}
}
return obj;
}
So if you have JSON (i.e. text representing an object), you can remove all instances of a particular property using something like:
var jsonText = '{ ... }';
var obj = JSON.parse(jsonText);
removeProp(obj, '__metadata');
jsonText = JSON.stringify(obj);
The function could take a third parameter that specifies if it should check nested objects or not.

How do you recursively remove nested objects that contain an empty array?

I initially receive an AJAX response of {"B":{"1":"100","3":{"AA":256}},"A":100} and converted to a javascript object:
var jsonOBJ = {};
jsonOBJ = jQuery.parseJSON(data);
Future responses can be subsets or supersets of the initial response. If the value of a table is unchanged at the server, the stagnant data is replaced with an empty array. Example:
{"B":{"1":"90","2":200,"3":[]}}
{"B":[],"A":20}
Everytime an AJAX response is received, the object is updated with:
jQuery.extend(true, jsonOBJ, jQuery.parseJSON(data));
But I need the javascript object to keep the unchanged portions, so I need to end up with an object that would be equivalent to the following with the example responses above:
jsonOBJ = jQuery.parseJSON('{"B":{"1":"90","2":200,"3":{"AA":256}},"A":20}');
My preferred option would be to remove the empty objects from the converted response. Is there an existing function or a modification to the jQuery extend function that would do this?
You can remove the elements in your response with empty arrays with this code.
It cycles through the top level, looking for any empty arrays and removing them. Any objects it finds, it recurses into to also remove empty arrays in them:
// make sure the ES5 Array.isArray() method exists
if(!Array.isArray) {
Array.isArray = function (arg) {
return Object.prototype.toString.call(arg) == '[object Array]';
};
}
function removeEmptyArrays(data) {
for (var key in data) {
var item = data[key];
// see if this item is an array
if (Array.isArray(item)) {
// see if the array is empty
if (item.length == 0) {
// remove this item from the parent object
delete data[key];
}
// if this item is an object, then recurse into it
// to remove empty arrays in it too
} else if (typeof item == "object") {
removeEmptyArrays(item);
}
}
}
var jsonOBJ = {};
jsonOBJ = jQuery.parseJSON(data);
removeEmptyArrays(jsonOBJ);
You can see it work here: http://jsfiddle.net/jfriend00/U6qMH/
Not really what I asked for, but removing the empty arrays from the JSON string is a solution:
jQuery.extend(true, jsonOBJ, jQuery.parseJSON(data.replace(/"[A-Za-z0-9_]*":\[\]/,'').replace(/{,/,'{').replace(/,}/,'}')));
this will complete the function ;)
removeEmptyArrays(data) {
for (var key in data) {
var item = data[key];
// see if this item is an array
if (Array.isArray(item)) {
// see if the array is empty
if (item.length == 0) {
// remove this item from the parent object
delete data[key];
} else {
this.removeEmptyArrays(item);
}
// if this item is an object, then recurse into it
// to remove empty arrays in it too
} else if (typeof item == "object") {
this.removeEmptyArrays(item);
}
}
},

Categories

Resources