accessing field value in array of objects in javascript - javascript

I need to access an element with a certain field value for the cdOption field in this array of objects of type possibleOptions:
[Object { cdOption="OPT001", description="Description 1", type="STRING"},
Object { cdOption="OPT002", description="Description 2", type="STRING"},
Object { cdOption="OPT003", description="Description 3", type="STRING"}]
The field value I'm looking for is extracted from antoher object in an array and so I'm alreay in a $.each cycle.
Can I avoid entering another cycle in order to loop the possibleOptions object and look for the specified field value?
I've tried with
possibleOptions[option.cdOpzione] but it doesn't work, is there a way to do this? I know I'm missing something.
current $.each code:
$.each(oldOptions, function(key, option) {
$.each(possibleOptions, function(key, possibleOption) {
if (option.cdOption === possibleOptions.cdOption) {
console.log(option.cdOption);
console.log(possibleOption.description);
}
});
});

In a generic way, you can't avoid the extra cycle. There may be particular solutions though, depending on your circumstances.
Solution 1
You could avoid it if you restructure your data, to have possibleOptions be an object with the values in cdOption as keys and an object with description and type as value.
Example:
var possibleOptions = {
'OPT001' : { description:"Description 1", type:"STRING" },
'OPT002' : { description:"Description 2", type:"STRING" },
'OPT003' : { description:"Description 3", type:"STRING" }
};
var val = 'OPT002';
console.log(possibleOptions[val]);
Solution 2
Another thing you could do if the cdOption is always of the form OPT-index- where -index- is 1+ the index in the array is to parse the value you're looking for, extract the -index-, parseInt and subtract one.
Example:
var val = 'OPT002';
var index = parseInt(val.substring(3))-1;
console.log(possibleOptions[index]);
Demo for both: http://jsbin.com/opojozE/1/edit

Array.filter can return an array of the elements matching a conditon. e.g. if you want to find the object (or objects) with cdOption == "OPT002", you could say:
var matches = possibleOptions.filter(
function( element ) {
return ( "OPT002" == element.cdOption );
}
);
and matches will contain:
[
{ cdOption="OPT002", description="Description 2", type="STRING"}
]
if you're just looking for one match:
var myOption = (matches.length > 0) ? matches[0] : null;
If you need to support older browsers that lack Array.filter, see Array filter method at MDN for a way to add it.

Related

Null Values in array of objects

I am creating objects when textbox having some values (using ng-blur and textbox.value!==undefined) and then putting these objects in an array (all working fine here).
When I click on checkbox (checkbox model bind with textbox ng-required) I need to delete that particular object having that textbox value.
I am using:
arr.splice(index,1);
to remove that particular object from array (by matching it's name like "monthly" or "quarterly" etc.), but it is creating null at that particular position.
for e.g. [object,object,object]
[
{name:"monthly",
amount:1000 },
{name:"quarterly",
amount:1200 },
{name:"yearly",
amount:1300 }
]
after removing all element it shows [] and when I add another new object it displays [3:object] and it's content as [null,null,null,object];
or
if I remove middle object say name:"quarterly", it shows [object,object] but after adding a new object it display array as [object,object,null,object] with length of array as 4.
Why is there null and how can I remove that from array. (don't want to iterate again to check null).
It is difficult to say why your code creates the null values without have a look to it.
But I can say you that it is not the expected behaviour.
You can see this example to get some inspiration:
var data = [
{name:"monthly",
amount:1000 },
{name:"quarterly",
amount:1200 },
{name:"yearly",
amount:1300 }
];
var newObjectToBeAdded = { name: "daily", amount:"100" }
function showObjects()
{
document.body.innerHTML += data + '<hr>';
}
function deleteObjectByName( objectName )
{
for( var i = 0; i < data.length; i++ )
{
if( data[ i ].name == objectName )
{
data.splice(i, 1);
}
}
}
function addObjectToData( newObject )
{
data.push( newObject );
}
showObjects();
deleteObjectByName( "quarterly" );
showObjects();
addObjectToData( newObjectToBeAdded );
showObjects();
Just to throw a guess out, maybe you are accidentally duplicating the array. Maybe in some point of your code you are doing something like this:
var new_array = original_array.splice( index );
Or creating the new array in the loop you use to find the target object, or using some kind of intermediate array, etc.
Hope it helps!
var arrayWithoutNulls = myArray.filter(function(val) {
if (val) {
return val;
}
});

filtering matching values from list of object using underscore

I am using UnderscoreJs in my project. I have to filter an array containing object having properties. I need to filter based on the values. The value can be of any property of the object. ex: "mini" should fetch both "toyota" and "Honda" since "mini" is present as part of both the objects
[{ name:"Toyota minivan", id:"506", size: "large" }, { name:"Honda Civic", id:"619", size: "mini" }]
How to do using Underscore. I have tried the following approach but not working.
var searchStr="mini";
var evens = _.filter([arrayData], function(obj){ return _.contains(obj, searchStr); });
Can you please let me know where I am going wrong?
_.contains only works on arrays, so you need to grab the values from each object first and then check if any of them contain the search string. I've used some in this example, together with indexOf to match the string.
var searchStr="mini";
var mini = _.filter(arr, function (obj) {
return _.values(obj).some(function (el) {
return el.indexOf(searchStr) > -1;
});
});
DEMO
Well, I have done this with simple if condition so that in future if you want to list mini in one array and large in one array so you can do easily. I have checked the object property if matched then assigned to new list. here is my code. and check out demo here fiddle
var list=[{ name:"Toyota minivan", id:"506", size: "large" },
{ name:"Honda Civic", id:"619", size: "mini" },
{name:"zen",id:"606",size:"mini"}];
var result=_.filter(list, function(obj){
if(obj.size=='mini'){
var matchedcars=obj;
console.log("result"+JSON.stringify(matchedcars));
}
return matchedcars;
});
alert("result"+JSON.stringify(result));

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

Get the lower integer id not already used in Javascript

I have a list of JS objects defined by an integer ID.
objects = [{
id: 0,
type: 'null'
}, {
id: 1,
type: 'foo'
}, {
id: 2,
type: 'bar'
}];
I implemented a function to remove an element from my list :
removeObject = function(o){
objects.splice(objects.indexOf(o), 1);
}
My problem is that I need to create a function to add a new item in my list with a id not already used (for example the lower positive integer not present in the list).
I tried to do something like that but it did not work when I remove the object 0 (for example).
addObject = function(type){
objects.push({
id: objects.length,
type: type
});
};
How can I do this ?
EDIT 1
According to your answers, I assume that the best solution in term of performance is to just use a topId which is always incremented when I add a new object in my list.
But that do not answer to my requierement. Actually I think that #X-Pippes response could be good.
Should I do someting like that :
objects = [{
id: 0,
type: 'null'
}, {
id: 1,
type: 'foo'
}, {
id: 2,
type: 'bar'
}];
// Init available ids list with the default value
availableIds = [objects.length];
removeObject = function(o){
// Remove the object from the list
objects.splice(objects.indexOf(o), 1);
// Add its id to the available ids list
availableIds.push(o.id);
}
addObject = function(type){
// Get lower id available
var newId = Math.min.apply(Math,availableIds);
// Push the new object with the id retrieved
objects.push({
id: newId,
type: type
});
// Remove used id from the available ids list
availableIds.splice(availableIds.indexOf(newId), 1);
// Add a default id if available list is empty
if(availableIds.length < 1) availableIds.push(objects.length);
};
if you remove for instance 0 and the next addObject is 0 you have to do something like:
keep a list [initial empty] with every ID removed. When you need to add a new one, pick the shorter, add and delete from list.
Also keep a var with the biggest ID added. If the previous list is empty, add +1 to the var and addObject with that id
Use the correct structures. A JavaScript object will do the job. It guarantees that you only get one item for key, you can look up and remove by key in probably O(1)ish. No point trying to re-implement it in a less efficient manner, which will be O(n) lookup.
var structure = {
objects : {},
topId : 0
}
structure.add = function(item) {
var id = this.topId ++;
structure.objects[id] = item;
}
structure.add("thing")
structure.add("other thing")
structure.add("another thing")
structure.objects
>>> Object {0: "thing", 1: "other thing", 2: "another thing"}
structure.objects[1]
>> "other thing"
Then the normal index operations to get/set/delete.
If you use that function then you have an invariant (guarantee) on your data structure that you won't use the same ID twice.
You need a function to find the first free number:
addObject = function(type){
objects.push({
id: firstOpenIndex(),
type: type
});
};
firstOpenIndex = function() {
for(var idx = 0; true; i++) {
var found = false;
for(var o in objects) {
if (objects[o].id == idx) {
found = true;
break;
}
}
if (!found) return idx;
}
}
In Javascript MaxInt is 9007199254740992. Why not just keep incrementing?
You can and probably should just use an array(s) like:
objects.type=['null','foo','bar'];
to add an object see:
How to append something to an array?
to find a value: var index = objects.type.indexOf('foo');
to find 1st empty field var index = objects.type.indexOf(''); which you can use to find the element for adding (if index is -1 use objects.type.length) if you "delete" an element by setting it to "" or... unless you have specific reason for keeping the "ID" static (in this case the array index), remove the element and only append new ones to the end
to remove an element see:
How do I remove a particular element from an array in JavaScript?
which will allow you to just push/append the next data.
if you need a new object array with empty fields to fill because you get new data to track:
object.newField=new Array(objects.type.length);
If you get to this point where your object contains multiple arrays, you will probably want to create functions for insert/add and delete/remove, so you don't do an operation on 1 and not the other.
Everything is already built in (read likely already pretty fast) and you don't need to reinvent constructors for your really cool object type.

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