angular, strip unused data before doing a lodash _.isEqual - javascript

So I have am trying to compare 2 objects using lodash's _.isEqual method, I have pretty straight forward function that checks like so
function findMatchingQuery(savedSearch) {
if (_.isEqual(savedSearch.data.document.query, $scope.searchResults.minify())) {
return true;
}
}
The data has changed a bit and I need to pull out a piece of data inside before I do a compare.
So the each of those objects has this format -
{
"name": "item name",
"showMore": boolean,
"filters": []
}
And what I would like to do is strip out the showMore node. I tried to add the some vars using _.remove, however it seems this does not work because remove is looking for a key and value.
var modifiedSavedSearch = _.remove(savedSearch.data.document.query, { "showMore" });
var modifiedCurrentSearch = _.remove($scope.searchResults.minify(), { "showMore" });
Is there a simple way to strip away those parts of the object before running the _.isEqual on them? Doesn't have to be lodash. Thanks!

You can delete the attribute, like:
delete savedSearch.data.document.query.showMore
You can use _.omit to remove it, or you can use _.pick to pick the rest of the attributes

Yeah, omit should do what you are looking for:
var modifiedSavedSearch = _.omit(savedSearch.data.document.query, { "showMore" });

If you want to get rid of it completely, you can do the following:
// assuming this is your variable
var myVar = {
"name": "item name",
"showMore": boolean,
"filters": []
};
// delete the unwanted property
delete myVar.showMore;

Related

JavaScript - How to dynamically add to a nested object array

I am trying to make a messenger bot that can create buttons based on a number I enter. The code looks like this:
let messageData = {
"attachment": {
"type": "template",
"payload": {
"template_type": "button",
"text": text[1],
"buttons":[]
}
}
}
The part that says "buttons":[] is where I want to add buttons (inside the []) according to this format:
{
"type":"postback",
"title":"button" + i //where i is the button number,
"payload":"button" + i
}
How would I go about doing this?
For your example you can do this:
messageData.attachment.payload.buttons.push(obj)
the . accesses the object's key, which can also be done this way messageData['attachment']
The difference between
messageData.attachment
and
messageData['attachment']
is that the second one can take a variable instead of a string, e.g.
var use_key = 'attachment';
messageData[use_key];
will access the same as the other two above.
JSON is just short for JavaScript Object Notation. And you make it exactly like your second example:
{
"type":"postback",
"title":"button" + i //where i is the button number,
"payload":"button" + i
}
You can assign it to a variable to pass it into the push, or just exactly as it is. Not much different from a string or number. Don't let all the extra information scare you.

Sorting of Arrays in Object with recursive search

I am trying to sort every Array by Name in an JSON-Object using Node.js.
I manage to sort just the Array with Underscore.js, but how can I input the whole Object and just get the Object back finished sorted?
Thinking about looking through the object recursively for Arrays and sort every one of them, but how can I do that?
Here is an example Object with just sorting the Array:
var _ = require("./underscore.js")
var jsonObject = { "Configuration":{
"$":{
"xmlns":"http://www.example.com/"
},
"ApplicationInstance":{
"Description":"Description text here.",
"Name":"Server1",
"Class":"System",
"Visibility":"System",
"CustomerCreated":"0",
"Active":"0",
"IntroducedIn":{
"$":{
"xsi:nil":"true",
"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance"
}
},
"Property":[
{
"Description":"JMS publisher destination type.",
"Name":"jmsJBossPublisher.destinationType",
"Class":"System",
"Visibility":"System",
"LanguageIndependantDescriptionKey":"ActivityGateway-JMSSenderConfiguration.jmsJBossPublisher.destinationType.DESCKEY",
"LanguageIndependantNameKey":"ActivityGateway-JMSSenderConfiguration.jmsJBossPublisher.destinationType.NAMEKEY",
"CustomerCreated":"1",
"Active":"0",
"IntroducedIn":"1.1",
"AttributeValue":"QUEUE",
"AttributeDataTypeName":"String"
},
{
"Description":"jmsConnectionFactory properties.",
"Name":"jmsConnectionFactory.jndiNameForJmsConnectionFactory",
"SecurityClass":"System",
"Visibility":"System",
"LanguageIndependantDescriptionKey":"ActivityGateway-JMSSenderConfiguration.jmsConnectionFactory.jndiNameForJmsConnectionFactory.DESCKEY",
"LanguageIndependantNameKey":"ActivityGateway-JMSSenderConfiguration.jmsConnectionFactory.jndiNameForJmsConnectionFactory.NAMEKEY",
"CustomerCreated":"1",
"Active":"0",
"IntroducedIn":"1.1",
"AttributeValue":"ConnectionFactory",
"AttributeDataTypeName":"String"
}
],
"ServerId":"1",
"ApplicationName":"ActivityGateway",
"InstanceID":"1"
}
}
};
console.log(_.sortBy(jsonObject.Configuration.ApplicationInstance.Property,'Name'))
_.sortBy returns a cloned array, so you'll need to override the previous value.
Try adding this line:
jsonObject.Configuration.ApplicationInstance.Property = _.sortBy(jsonObject.Configuration.ApplicationInstance.Property,'Name')

Searching json array for a specific attribute

Actually I want to search an attribute's value in an json array for one of its child. Now one condition is that the attribute will not be there in all the child's of the array. This is my json array.
[{
"heading1":"heading1",
"heading2":"heading2",
"heading3":"heading3",
"heading4":"heading4",
"heading5":"heading5",
"heading6":"heading6"
},
{
"column1":65536,
"column2":"school",
"column3":"testing purpose",
"column4":"DESKTOP",
"column5":"ACTIVE",
"column6":true,
"column7":"a6cc82e0-a8d8-49b8-af62-cf8ca042c8bb"
},
{
"column1":98305,
"column2":"Nikhil",
"column3":"Test",
"column4":"LAPTOP",
"column5":"ACTIVE",
"column6":true,
"column7":"a6cc82e0-a8d8-49b8-af62-cf8ca042c8bb"
}]
So presently I am working with the each loop but like this
var obj = $.parseJSON(JSON.stringify(response));
$.each(obj, function () {
console.log("heading1", this['heading1']);
});
Here response comes from mserver and it is the json array
Now I want to know can I search for this attribute in the json array without using a loop in jQuery.
Based on your sample code what I understand you have is an array of objects and you want to find objects with one specific property and or value:
This will return true if the object has the property
var results= arr.filter(function(item){ return item.hasOwnProperty("column5"); });
Or you can perform additional action when you find the property:
arr.filter(function(item){
if (item.hasOwnProperty("column5")) {
return item["column5"] === 'demo 01'; //or item.column5 === 'demo 01'
}
return false;
});
This only works on IE9+ if you need this to run in older versions of IE, please follow the instructions under polyfill:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
The you can check like
var obj = $.parseJSON(response);
$.each(obj, function (index,value) {
if(typeof obj[index].heading2 !== "undefined")
{
alert(obj[index].heading2);
}
when in other object of array element not find then it returns undefined. and you can check like that.
you can check in this http://jsfiddle.net/gKRCH/
It's best to use a loop. But if the format of the JSON is regular, you could regex for the value in the response string.
I'm not recommending this method, just pointing out that it exists.
var value = "heading1";
if( (new RegExp('"' + value + '"')).test(response) ){
// Found value
};
Here, we take the required value, wrap it in quotation marks and search for it in the response.
This has several issues, such as:
It might find the pattern in a property name
If the value could contain regex special characters, they'll need escaping.
If your JSON contains values with escaped quotation marks, you could get a false positive from partial matches.
That's why it depends on you knowing the format of the data.
EDIT:
You can solve issue 2 by using this condition instead of regex. But it gives you less flexibility.
response.indexOf('"' + value + '"') !== -1
Try this,
$.each(object,function(key, value){
console.log(key);
console.log(value);
});
You can use this JS lib; DefiantJS (http://defiantjs.com). This lib extends the global object JSON with the method "search" - with which, you can perform XPath queries on JSON structures. Like the one you have exemplified.
With XPath expressions (which is standardised query language), you can find whatever you're looking for and DefiantJS will do the heavy-lifting for you - allowing your code to be neat and clean.
Here is the fiddle of this code:
http://jsfiddle.net/hbi99/q8xst/
Here is the code:
var data = [
{
"heading1": "heading1",
"heading2": "heading2",
"heading3": "heading3",
"heading4": "heading4",
"heading5": "heading5",
"heading6": "heading6"
},
{
"column1": 65536,
"column2": "school",
"column3": "testing purpose",
"column4": "DESKTOP",
"column5": "ACTIVE",
"column6": true,
"column7": "a6cc82e0-a8d8-49b8-af62-cf8ca042c8bb"
},
{
"column1": 98305,
"column2": "Nikhil",
"column3": "Test",
"column4": "LAPTOP",
"column5": "ACTIVE",
"column6": true,
"column7": "a6cc82e0-a8d8-49b8-af62-cf8ca042c8bb"
}
],
res = JSON.search( data, '//*[column4="DESKTOP"]' );
console.log( res[0].column2 );
// school

JavaScript JSON parse by a given key without looping

Given a JSON string as this:
{
"__ENTITIES": [
{
"__KEY": "196",
"__STAMP": 1,
"ID": 196,
"firstName": "a",
"middleName": "b",
"lastName": "c",
"ContactType": {},
"addressCollection": {
"__deferred": {
"uri": "/rest/Contact(196)/addressCollection?$expand=addressCollection"
}
},
"__ERROR": [
{
"message": "Cannot save related entity of attribute \"ContactType\" for the entity of datastore class \"Contact\"",
"componentSignature": "dbmg",
"errCode": 1537
}
]
}
]
}
Is there a method to get just the __ERROR record, I know I can use
var mydata = json.parse(mydata) and then find it from the mydata object. But I was hoping there was a method to only return the ERROR field something like
json.parse(mydata, "__ERROR") and that gets only the information in the __ERROR field without turning the whole JSON string into an object
"Is there a method to get just the __ERROR record, I know I can use var mydata = json.parse(mydata) ... But I was hoping there was ... something like json.parse(mydata, "__ERROR")"
There may be libraries that do this, but nothing built in. You need to write code that targets the data you want.
The closest you'll get will be to pass a reviver function to JSON.parse.
var errors = [];
var mydata = JSON.parse(mydata, function(key, val) {
if (key === "__ERROR")
errors.push(val);
return val
});
without turning the whole json string into an object
That's hardly possible, you would need some kind of lazy evaluation for that which is not suitable with JS. Also, you would need to write your own parser for that which would be reasonable slower than native JSON.parse.
Is there a method to get just the __ERROR record
Not that I know. Also, this is an unusual task to walk the whole object tree looking for the first property with that name. Better access __ENTITIES[0].__ERROR[0] explicitly.
If such a function existed, it would have to parse the whole thing anyway, to find the key you're looking for.
Just parse it first, then get the key you want:
var mydata = JSON.parse(mydata);
var errorObj = mydata.__ENTITIES[0].__ERROR[0];
If you want, you may create your own function:
function parseAndExtract(json, key) {
var parsed = JSON.parse(json);
return parsed[key];
}

What's the best way to query an array in javascript to get just the items from it I want?

I have an array like this (with just over 3000 objects instead of the 3 here):
items = [{name:'charlie', age:'16'}, {name:'ben', age:'18'}, {name:'steve', age:'18'}]
What's the best way to return an array with just the objects of people who are 18? So I want:
items = [{name:'ben', age:'18'}, {name:'steve', age:'18'}]
The best I can think of is this (using jQuery):
newArray = []
$.each(items, function(index, item) {
if(item.age=='18') {
newArray.push(item)
}
})
Considering that there's 3000 thousand objects, and also that I'll be doing that comparison up to fifty times in one go, that's a lot of looping. Is there a better way?
You can use pure javascript
var wanted = items.filter( function(item){return (item.age==18);} );
And if your browser does not support the 1.6 version of javascript you can find an implementation of the filter method at https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter
Update
Speedwise there is a huge varying (had an error in the test) difference from a normal loop (depending on browser).. Have a look at this little test i made at http://jsperf.com/array-filter-vs-loop/3
Get matched item and items using find() and filter() method
If you want first matched single item, use find() method which returns single object.
If you want all matched , use filter() method which returns array of objects.
let items = [{name:'charlie', age:'16'},
{name:'ben', age:'18'},
{name:'steve', age:'18'}]
let all = items.filter(item=> item.age==='18')
console.log(all);
let single = items.find(item=> item.age==='18')
console.log(single);
If you're going to do the search often it may be best to keep a version of your data in a form that is quick to access.
I've used underscore.js (http://documentcloud.github.com/underscore/) to make it easy for myself, but this code here will create an object that holds your data indexed by the age field.
You end up with something that looks like this:
{
"16": [
{
"name": "charlie",
"age": "16"
}
],
"18": [
{
"name": "ben",
"age": "18"
},
{
"name": "steve",
"age": "18"
}
]
}
The code:
var itemsByAge = _(items).reduce(function(memo, item) {
memo[item.age] = memo[item.age] || [];
memo[item.age].push(item);
return memo;
}, {});
alert(JSON.stringify(itemsByAge["18"]));
No matter which method you choose (items.filter or any "query language" for json), a for loop is inevitable.
If performance is a concern, I would recommend you to use pure javascript instead of libraries like jQuery which will add overheads to the whole processing as is evident here.
Thus, your code would look like:
var newArray = [];
for(var i=0;i<items.length;i++) {
var item = items[i];
if(item.age == '18') {
newArray.push(item);
}
});
making use of javascript magnificent function eval() which evaluates string as code at runtime, we can define a prototype method for Array type
Array.prototype.where = function (query) {
var newArray = [];
for(var i=0; i<this.length; i++) {
var item = this[i];
if(eval( "item" + query )) {
newArray.push(item);
}
}
return newArray;
};
and use it with any array, passing the query as string
var newArray= items.where('.age >= 18');
Use the filter method of the array, it calls the provided callbackfunction once for each element in an array.
array.filter(<callbackfucntion>[, <Object to use>])
once i had such problem and i solved it like this
1- create an array of array
2- each index create an Index record
e.g.
var pAry=[];
var cAry=[{name:'ben', age:'18'}, {name:'steve', age:'18'}]
pAry[17]=cAry;
This way when u require person with age 18, you will get on index 17.

Categories