Assume you have an array:
var arrStateCityAll=['CA_Alameda','CA__Pasadena','CA_Sacramento','NY_Albany','NY_Buffalo','NY_Ithaca']
Is there an easy way using javascript and/or jQuery to filter the arrStateCityAll to get a new array (a subset of arrStateCityAll); something like this:
// return's ['CA_Alameda','CA__Pasadena','CA_Sacramento']
var arrStateCityCA=FilterArray('CA',arrStateCityAll);
Likely you want to do a regex on each item. You can do this with jQuery's grep function.
http://api.jquery.com/jQuery.grep/
You can use javascript's Array.filter.
var arrStateCityAll = ['CA_Alameda','CA__Pasadena','CA_Sacramento','NY_Albany','NY_Buffalo','NY_Ithaca']
var arrStateCityCA = arrStateCityAll.filter( function (element) {
return element.indexOf("CA_") == 0;
});
The mozilla documentation linked to above has a solution for browsers that don't implicitly support filter.
This should work.
var arrStateCityCA = [];
for (var i = 0;i<arrStateCityAll.length;i++){
if (arrStateCityAll[i].substr(0,2) == 'CA'){
arrStateCityCA.push(arrStateCityAll[i]);
}
}
You could use jQuery.grep
var arrStateCityCA =
$.grep(arrStateCityAll,function(el,i){return (el.substring(0,2)=='CA')});
Demo at jsfiddle
To implement you actual FilterArray function as shown in your post you could do
function FilterArray(state,arr){
return $.grep(arr,
function(el,i) {return (el.substring(0,2)==state)}
);
}
This makes a few assumptions.
State is always 2 chars.
State is always the first 2 chars.
And of course remember case-sensitivity (this function is case sensitive) ie 'CA' not equal to 'Ca'.
if you are going to have an undescore between your state and city name, you can split on the underscore and test against the first array value
function getSubSetByState(set,state) {
var result = [];
for(var i=0,l=set.length;i<l;++i) {
if(set[i].split('_')[0] === state) {
result.push(set[i]);
}
}
return result;
}
Use if by giving it the set of places, and then the state you are searching for.
Related
I have search through quite a lot of questions here, but havent found one that i think fits my bill, so if you know of one please link to it.
I have an array that i want to search through for a specific number and if that number is in the array, i then want to take an action and if not then another action.
I have something like this
var Array = ["1","8","17","14","11","20","2","6"];
for(x=0;x<=Array.length;x++)
{
if(Array[x]==8)
then change picture.src to srcpicture1
else
then change picture.src to srcpicture2
}
but this will run the lenght of the array and end up checking the last element of the array and since the last element is not 8 then it will change the picture to picture2.
Now i can see why this happens, i just dont have any ideas as to how to go about checking if an array contains a specific number.
Thanks in advance.
What you can do is write yourself a function to check if an element belongs to an array:
function inArray(array, value) {
for (var i = 0; i < array.length; i++) {
if (array[i] == value) return true;
}
return false;
}
And the just do:
var arr = ["1","8","17","14","11","20","2","6"];
if (inArray(arr, 8)) {
// change picture.src to srcpicture1
} else {
// change picture.src to srcpicture2
}
It's a lot more readable to me.
For extra points you can add the function to the array prototype like so:
Array.prototype.has = function (value) {
for (var i = 0; i < this.length; i++) {
if (this[i] === value) return true;
}
return false;
};
And then the call would be
if (arr.has(8)) // ...
Pushing this even further, you can check for indexOf() method on array and use it - if not - replace it with the code above.
P.S. Try not to use Array for a variable name, since it's reserved for the actual array type.
use this
http://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/IndexOf
ie version
https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/IndexOf#Compatibility
Why don't just you abort the loop when you find the right number :
for(x=0;x<=Array.length;x++)
{
if(Array[x]==8) {
//change picture.src to srcpicture1
break;
}
}
You could sort the array first then check the array only up to the point at which a number would be in the array, were it to exist.
If you have unique keys and a faster retrieval is what you care about a lot, you can consider using a map instead of an array (if there's a hard-bound case of using an array, then it won't work of course). If using a map, you just check "if( num in arr ) ".
I've already read a few questions here but can't seem to find exactly what I'm looking for. Basically, I need to know if any of the elements present in an array are present in a string. An example:
var currentHref = "http://www.vorcu.com/hello";
var urls = [
"vorcu.com",
"neutronico.com",
"word2.com"
];
So, I need to know if any of the elements in "urls" coincide with any of the text present in "currentHref". Any ideas?
Thanks!
Loop through the array and use search:
str.search(arrItem)
will return the position of the match, or -1 if it isn't found.
Something like this:
for (var i = 0; i < urls.length; i++) {
if (currentHref.indexOf(urls[i]) != -1) {
alert(urls[i]); // found occurence, break or continue
}
}
Or RegExp way (above way is preferred):
var isInArray = RegExp(urls.join('|')).test(currentHref); // true|false
or
var matches = currentHref.match(urls.join('|')); // array of matches ["vorcu.com"]
Everyone is providing the Javascript answer (which I fully support), but just because you mention jQuery I figure I'd provide an alternative:
var curHref = window.location.hostname.split('.'),
// i imagine your static string was just for test purposes
checkHref = curHref[1]+'.'+curHref[2],
urls = [
"vorcu.com",
"neutronico.com",
"word2.com"
];
if($.inArray(checkHref,urls) > -1){
// its in there, do your magic
}
This creates the object I assume you wanted to check (hostname minus www) and if it matches any of the items in urls using the jQuery inArray method.
A function like the following should work:
function containsAny(str, arr) {
for (var i = 0; i < arr.length; i++) {
if (str.indexOf(arr[i]) !== -1) {
return true;
}
}
return false;
}
Alternately you could use the slower but more terse:
RegExp(arr.join('|')).exec(str);
You could use the some method, which is supported by many browsers:
var currentHref = "http://www.vorcu.com/hello";
var urls = [
"vorcu.com",
"neutronico.com",
"word2.com"
];
var containsAny = urls.some(function(x) { return currentHref.indexOf(x) >= 0; });
For compatibility with browsers where some is not supported, the MDN article I've linked provides an implementation you can use.
Make a foreach and then check indexOf ;)
I am trying to find a model within a collection with an attribute equal to html select option value.
<div id="hospital-details">
<select name="hospitalnames">
<option><%- model.get('name') %></option>
</select>
</div>
whenever hospital name is changed, jquery change callback is triggered to find locationModel with selected option value as attribute value as shown below,
$('select[name="hospitalnames"]').change(function() {
var name = $(this).val();
locationListCollection.each(function(locationModel) {
if ($.trim(locationModel.get('name')) == $.trim(name)) {
that.locationModel = locationModel;
return false; // control is returned to underscore.min.js
}
});
});
console.log(that.locationModel); // this is not being displayed at all
After the locationModel with an attribute is found, I am unable to come out the loop. Any help ? At this moment I have looked into
this but without success.
You're using the wrong method if you're searching for the first match. Collections have lots of Underscore methods mixed in, in particular they have find mixed in:
find _.find(list, iterator, [context])
Looks through each value in the list, returning the first one that passes a truth test (iterator), or undefined if no value passes the test.
Something like this:
var name = $.trim($(this).val());
that.locationModel = locationListCollection.find(function(locationModel) {
return $.trim(locationModel.get('name')) == name;
});
and if the names in your model are pre-trimmed and nice and clean, then you could use findWhere:
findWhere collection.findWhere(attributes)
Just like where, but directly returns only the first model in the collection that matches the passed attributes.
like this:
var name = $.trim($(this).val());
that.locationModel = locationListCollection.findWhere({ name: name });
BTW, this:
console.log(locationModel);
won't give you anything because locationModel and that.locationModel are different things.
You can always go oldschool.
$('select[name="hospitalnames"]').change(function() {
var name = $(this).val();
for (var i = 0; i < locationListCollection.length; ++i) {
var locationModel = locationListCollection.models[i];
if ($.trim(locationModel.get('name')) == $.trim(name)) {
that.locationModel = locationModel;
break;
}
}
});
Try this,
var name = $(this).val();
var flag=true;
locationListCollection.each(function(locationModel) {
if (flag && $.trim(locationModel.get('name')) == $.trim(name)) {
that.locationModel = locationModel;
flag=false;
//return false;// to break the $.each loop
}
});
The short is no.
If you take a look at underscore's source you'll see that they use a breaker object to quickly stop a .each() but that is only available internally.
I would not recommend this but you could always modify the source to expose this breaker object (see baseline setup in the annotated source
http://underscorejs.org/docs/underscore.html). Then you would just return this object instead of returning false. But you would probably need to remove the native forEach call to keep the behaviour consistent. So it's not worth it!
_.each(function(arr) {
if(condition) {
return _.breaker; // Assuming you changed the source.
}
});
Since you are searching for a single item instead of .each() use:
var locationModel = _.find(arr, function(item) {
return $.trim(locationModel.get('name')) == $.trim(name);
));
I'm using $.grep() to pull back a set of JSON results like so:
myObject.appJSON = jQuery.grep(myObject.appJSON, function (a) {
return a.category == "Entertainment";
});
and it works fine. But what I really want to do eventually is have several checkboxes so that that I can filter on several different things. I realize to do that I can just do something like:
myObject.appJSON = jQuery.grep(myObject.appJSON, function (a) {
return (a.category == "Entertainment" && a.category == "Business");
});
But my real question here is how to have this happen dynamically, so I can essentially build up a string of features for the grep to return. Maybe I'm showing how novice I am here but it would almost be nice to be able to generate the long filter string then just pop it into the return. It looks like as it is now, the return has to be hard coded.
I realize this is probably simple but there's very little out there on the net about how to do this kind of thing.
Thanks in advance!
You can search an array like this:
myObject.appJSON = jQuery.grep(myObject.appJSON, function (a) {
return $.inArray(a.category, someArray) > -1;
});
I think you can regexp the match:
var filter = function(categories) {
var obj = [];
$.each(categories.split(' '), function(cat) {
obj.push(jQuery.grep(myObject.appJSON, function (a) {
return cat.test(a.category);
}));
});
return obj;
}
var filtered_array = filter('Entertainment Business');
You could use eval() to create your grep logic dynamically. Or you could create a regular expression matching all your categories. But the easiest thing to do is create an object which contains your categories and check if a.category is one of them.
var categories = {
"Entertainment": 1,
"Business": 1
};
myObject.appJSON = jQuery.grep(myObject.appJSON, function (a) {
return categories[a.category];
});
I have an array of items (terms), which will be put as <option> tags in a <select>. If any of these items are in another array (termsAlreadyTaking), they should be removed first. Here is how I have done it:
// If the user has a term like "Fall 2010" already selected, we don't need that in the list of terms to add.
for (var i = 0; i < terms.length; i++)
{
for (var iAlreadyTaking = 0; iAlreadyTaking < termsAlreadyTaking.length; iAlreadyTaking++)
{
if (terms[i]['pk'] == termsAlreadyTaking[iAlreadyTaking]['pk'])
{
terms.splice(i, 1); // remove terms[i] without leaving a hole in the array
continue;
}
}
}
Is there a better way to do this? It feels a bit clumsy.
I'm using jQuery, if it makes a difference.
UPDATE Based on #Matthew Flaschen's answer:
// If the user has a term like "Fall 2010" already selected, we don't need that in the list of terms to add.
var options_for_selector = $.grep(all_possible_choices, function(elem)
{
var already_chosen = false;
$.each(response_chosen_items, function(index, chosen_elem)
{
if (chosen_elem['pk'] == elem['pk'])
{
already_chosen = true;
return;
}
});
return ! already_chosen;
});
The reason it gets a bit more verbose in the middle is that $.inArray() is returning false, because the duplicates I'm looking for don't strictly equal one another in the == sense. However, all their values are the same. Can I make this more concise?
var terms = $.grep(terms, function(el)
{
return $.inArray(el, termsAlreadyTaking) == -1;
});
This still has m * n performance (m and n are the lengths of the arrays), but it shouldn't be a big deal as long as they're relatively small. To get m + n, you could use a hashtable
Note that ECMAScript provides the similar Array.filter and Array.indexOf. However, they're not implemented in all browsers yet, so you would have to use the MDC implementations as a fallback. Since you're using jQuery, grep and inArray (which uses native indexOf when available) are easier.
EDIT:
You could do:
var response_chosen_pk = $.map(response_chosen_items, function(elem)
{
return elem.pk;
});
var options_for_selector = $.grep(all_possible_choices, function(elem)
{
return $.inArray(elem.pk, response_chosen_pk) == -1;
});
http://github.com/danstocker/jorder
Create a jOrder table on termsAlreadyTaking, and index it with pk.
var table = jOrder(termsAlreadyTaking)
.index('pk', ['pk']);
Then you can search a lot faster:
...
if ([] == table.where([{ pk: terms[i].pk }]))
{
...
}
...