Check for a value in Array - javascript

I'm trying to check for match in an array with PURE JAVASCRIPT. I don't know how to do this, I would appreciate your help.
var sites = new Array ("site1.com", "site2.com", "site3.com" ...);
// Sites array contains 100 values
var imgs = document.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
img = imgs[i].src;
// I'm trying to check if is in array,
// and don't waste a lot of size in code
if(img.match(sites)){
notHere(imgs[i]);
}
// This is the working way.
// Even if location is a.site1.com/b/, it will match
if (img.match("site1.com")) {
heReload(imgs[i]);
}
// Repeat this piece of code 100 times
}
}
NOTE: I don't want to check for an exact value. I want to simulate the match() function so if img = "http://a.b.c/d/" and in array is "b.c/", it executes function().

Your "sites" variable should be a regular expression rather than an array:
var sites = /\b(site1\.com|site2\.com|etc|etc)\b/
later:
if (img.match(sites))
......
If for some reason you prefer to keep "sites" in an array, you also can create a regular expression "on the fly":
var sites = ["site1.com", "site2.com", "site3.com"]
var sitesRegexp = new RegExp("\\b(" + sites.join("|").replace(".", "\\.") + ")\\b")
....
if (img.match(sitesRegexp)
......

Good use case for filter.
If you want to have it working on "old" browser :
var nativeFilter = Array.prototype.filter;
_.filter = _.select = function(obj, iterator, context) {
var results = [];
if (obj == null) return results;
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
each(obj, function(value, index, list) {
if (iterator.call(context, value, index, list)) results[results.length] = value;
});
return results;
};
It will return an empty array if nothing is found, otherwise, return an array containing the result(s)
> [1,2,3,4].filter(function(item) { return item == 4 } );
[ 4 ]
Source : Underscore.js
So now your code will look like this :
var sites = new Array ("site1.com", "site2.com", "site3.com" ...);
// Sites array contains 100 values
var imgs = document.getElementsByTagName( "img" );
for ( var i = 0; i < imgs.length; i++ ) {
var img = imgs[ i ].src;
var result = sites._filter( function( site ) {
return img.match( site )
});
// result is an array of matching sites
}

you can extend the Array prototype , so it supports all browsers ...
try this :
Array.prototype.myContains = function(obj) {
var i = this.length;
while (i--) {if (this[i] .indexOf(obj)>-1) return true; }
return false;
}
usage : var t=myArr.myContains(3);

Related

When to use array and when to use object?

I've read a lot of articles about objects and arrays lately but they had contrary info / facts for some reason. I need your help to learn once and for all: when it's best to use array and when object?
Obvious reason is to use array when you need specific order. What else? What about this example?
There's a lot of pushing
There's a lot of checking if array contains something
There's a lot of removing
Note that this example has much smaller numbers that I need (which is in thousands).
Code I wrote for this question, it has few things I would never do but for the sake of this question:
var x = [];
var y = [];
var z = [];
var clickedX = [];
var clickedY = [];
var clickedZ = [];
var count = 100;
for ( var a = 0; a < count; a++ ) {
//For the sake of this example: random int 1, 2 or 3
var type = Math.floor(Math.random() * 3) + 1;
createDiv( type );
}
function createDiv( thisType ) {
var self = this;
var div = self.div;
var type = thisType;
if( !div ) {
div = this.div = document.createElement( 'div' );
div.className = 'marker';
//Push to "right" array
if( type == '1' ) {
x.push( self );
}
else if ( type == '2' ) {
y.push( self );
}
else {
z.push( self );
}
//Attach click event
div.onclick = function() {
// X
var indexX = x.indexOf( self );
if( indexX > -1 ) {
//Push to new array
clickedX.push( self );
//Remove from old array
x.splice( indexX, 1 );
}
// Y
var indexY = y.indexOf( self );
if( indexY > -1 ) {
//Push to new array
clickedY.push( self );
//Remove from old array
y.splice( indexY, 1 );
}
// Z
var indexZ = z.indexOf( self );
if( indexZ > -1 ) {
//Push to new array
clickedZ.push( self );
//Remove from old array
z.splice( indexZ, 1 );
}
}; // onclick
} // if( !div )
} // createDiv()
Data example what Im currently dealing with:
// Data Im dealing with
objects = {
{ objects1: [
0: { object : [4-5 assigned values (int, string, array)] },
1: { object : [4-5 assigned values (int, string, array)] },
//etc
]
},
{ objects2: [
0: {object},
1: {object},
//etc
]
}
}
// 1. I need to iterate through every "object" in both "objects1" and "objects2"
// 2. I need to iterate through "array" in every "object" in "objects1"
for( /* "object" count in "objects1" */ ) {
//Do something for each "object" in "objects1"
for( /* items in "array" count */ ) {
//Do something for each item in "array"
}
}
// AND
for( /* "object" count in "objects2" */ ) {
//Do something for each "object" in "objects2"
}
Arrays
Basically, you need to use an array, when you have a list of consequent data, and you are going to work with it as a collection.
It easily adds, iterates, gets count and checks for existence.
It is difficult to remove items in an array.
Also, it stores order.
For example, if you have 10 integers, and you need to find the index of the minimum one, then it is logical to use an array.
Objects
Use objects, when your items have keys (especially, non-integer) and you are going to work with them one by one.
It is convenient to add, remove, check for existence properties.
However, it is less convenient to iterate through object properties, and absolutely inproper to get its count.
It is also impossible to store items' order.
Time complexity
Answering your question about pushing, checking for existence and removing:
Both property setting and array pushing takes O(1) time, but I strongly believe that the first one is a bit slower
Checking for existence takes the same O(1) time
Removing an element is what array is not designed for - it needs to shift all items and takes O(n) time, while you can remove a property for O(1)
Bad usage example
There are some really bad usages. If you have the following, then you use array or object wrong.
Assign a random value to an array:
var a = [];
a[1000] = 1;
It will change the length property of an array to 1001 and if you try to output this array, you will get the following:
[undefined,undefined,undefined,undefined... 1]
which is absolutely useless, if it is not done on purpose.
Assign consequent values to an object
var a = {};
for (var i = 0; i < 10; i++)
{
a[i] = 1;
}
Your code
Talking about your code, there are many and many ways to do this properly - just choose one. I would do it in the following way:
var items = [];
for (var i = 0; i < count; i++)
{
var o = {
type: Math.floor(Math.random() * 3) + 1,
isClicked: false
};
var div = document.createElement('div');
div.className = 'marker';
div.onclick = function() {
o.isClicked = true;
};
o.div = div;
items.push(o);
}
function GetDivs(type, isClicked)
{
var result = items;
if (type)
result = result.filter(function(x) { return x.type === type; });
if (isClicked !== undefined)
result = result.filter(function(x) { return x.isClicked === isClicked; });
return result;
}
Then, you will be able to get any items you want:
var all = GetItems(0); // or even GetDivs()
var allClicked = GetItems(0, true);
var allNotClicked = GetItems(0, false);
var divsTypeA = GetItems(1);
var clickedDivsTypeB = GetItems(2, true);
var notClickedDivsTypeC = GetItems(3, false);
With this usage, you don't need to remove any items at all - you just mark them as clicked or not, which takes O(1) time.
jQuery
If you use jQuery and data HTML attributes, then you won't need to use arrays or objects at all:
for (var i = 0; i < count; i++)
{
$('<div/>')
.addClass('marker')
.attr('data-type', Math.floor(Math.random() * 3) + 1)
.appendTo('body')
.click(function() {
$(this).addClass('clicked');
});
}
Now, you can use the selector to find any items:
var all = $('.marker');
var allClicked = $('.marker.clicked');
var allNotClicked = $('.marker:not(.clicked)');
var divsTypeA = $('.marker[data-type='1']');
var clickedDivsTypeB = $('.marker[data-type='2'].clicked');
var notClickedDivsTypeC = $('.marker[data-type='1']:not(.clicked)');
However, the last approach can produce lags if you really have thousands of records. At the same time, is it a good idea to have 1000 dynamic divs on your page, at all? :)
When all else fails run a test, Again it depends on what you intend to use the data structure for, everything is a trade off, performance || efficiency.
Be prepared to wait a few seconds for the tests to finish.
function gimmeAHugeArray( length ){
var arr = [];
for( var ii = 0; ii < length; ii++ ){
arr.push( (ii * 100000 ).toString(16) );
}
return arr;
}
function gimmeAHugeObject( length ){
var obj = {};
for( var ii = 0; ii < length; ii++ ){
obj[ (ii * 100000 ).toString(16) ] = ii;
}
return obj;
}
var hugeArray = gimmeAHugeArray( 100000 );
var hugeObject = gimmeAHugeObject( 100000 );
var key = (8000 * 100000).toString(16);
console.perf(function arrayGetWithIndexOf(){
var val = hugeArray.indexOf( key );
});
console.perf(function objectGetWithKey(){
var val = hugeObject[ key ];
});
console.perf(function arrayIterateAllProperties(){
var val = null;
for( var ii = 0, ll = hugeArray.length; ii < ll; ii++ ){
val = hugeArray[ii];
}
}, 50);
console.perf(function objectIterateAllProperties(){
var val = null,
key;
for( key in hugeObject ){
val = hugeObject[ key ];
}
}, 50);
<script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>
I'm going to answer your question from the comment above, from Solo.
The question is What to do if I need to do both with same data?
I have found that the best approach ( at least for me ) was to create an array, that may have empty nodes, but keep another array that will keep track of the ids that are populated.
It looks something like this:
var MyArray = function()
{
this.storage = [];
this.ids = [];
};
MyArray.prototype.set = function(id, value)
{
this.storage[id] = value;
this.ids[this.ids.length] = id;
};
MyArray.prototype.get = function(id)
{
return this.storage[id];
};
MyArray.prototype.delete = function(id)
{
delete this.storage[id];
};
This solution works quite well with both approaches, because you can delete anything at O(1), because everyone has a given ID, and you iterate it easily, because you have all of the IDs the values are stored at.
I have also created a really small class for my own usage, and it performs VERY well. Here's the link https://github.com/ImJustAskingDude/JavascriptFastArray . Here's a question I asked about these things: Javascript Array Performance .
Please read what I write there, this solution applies to a pretty particular situation, I do not know exactly if it applies to you.
That is why I asked you to read what is in those links I provided, I have written like 10 pages worth of material on this, even though some of it is pure garbage talk about nothing. Anyway, I'll write a couple of examples here as well, then.
Example:
Let us say you had data from the database, the data from the database is pretty much required to have unique integer IDs, but each user may have them spread over a wide range, they are MOST LIKELY not contiguous.
So you get the data from the database into objects, something like this:
var DBData /* well, probably something more descriptive than this stupid name */ = function(id, field1, field2, field3)
{
this.id = id;
this.field1 = field1;
this.field2 = field2;
this.fiedl3 = field3;
};
Given this class, you write all of the data from the database into instances of it, and store it in MyArray.
var data = new MyArray();
// YOU CAN USE THIS, OR JUST READ FROM DOM
$.get(/* get data from DB into MyArray instance */, function(data) { /* parse it somehow */ var dbdata = new DBData(/* fields that you parsed including ID */); data.set(ID, dbdata)});
and when you want to iterate over all of the data, you can do it like this:
Just create a function to create a new array, that has all of the data in a nice contiguous block, it would go something like this:
function hydrate(myarray, ids)
{
var result = [];
var length = ids.length;
if(!length)
{
return null;
}
var storage = myarray.storage;
for(var i = 0; i < length; i++)
{
result[result.length] = storage[ids[i]];
}
return result;
};
I use this method, because you can use it to select any configuration of objects into a contiguous array very easily.
One solution to handle arrays of arrays, would be to just modify MyArray to deal with that exclusively, or make a version of it, that handles it.
A different solution would be to rethink your approach, and maybe add all of the data in a single MyArray, but put all of the
objects1: [
0: { object : [4-5 assigned values (int, string, array)] },
1: { object : [4-5 assigned values (int, string, array)] },
//etc
]
},
{ objects2: [
0: {object},
1: {object},
//etc
]
}
into nice objects.
And seriously, read what I wrote in those links, there's my reasoning for everything there.

Find index of object in an array of prototypes Javascript

I am creating an app using jQuery mobile and need to get the index of an object in an array of prototypes.
The object, call team, is as follows:
var team = function (teamname, colour, rss_url, twitter_url, website, coords) {
this.teamname = teamname;
this.colour = colour;
this.rss_url = rss_url;
this.twitter_url = twitter_url;
this.website = website;
this.location = coords;
};
And the array itself looks like:
var teamlist = [32];
teamlist[0] = new team("Aberdeen","#C01A1A","http://www.football365.com/aberdeen/rss", "https://twitter.com/aberdeenfc","http://www.afc.co.uk/","57�09?33?N�2�05?20?W");
teamlist[1] = new team("Celtic","#C01A1A","http://www.football365.com/aberdeen/rss", "https://twitter.com/aberdeenfc","http://www.afc.co.uk/","57�09?33?N�2�05?20?W");
teamlist[2] = new team("Dundee","#C01A1A","http://www.football365.com/aberdeen/rss", "https://twitter.com/aberdeenfc","http://www.afc.co.uk/","57�09?33?N�2�05?20?W");
teamlist[3] = new team("Dundee United","#C01A1A","http://www.football365.com/aberdeen/rss", "https://twitter.com/aberdeenfc","http://www.afc.co.uk/","57�09?33?N�2�05?20?W");
teamlist[4] = new team("Hamilton Academical","#C01A1A","http://www.football365.com/aberdeen/rss", "https://twitter.com/aberdeenfc","http://www.afc.co.uk/","57�09?33?N�2�05?20?W");
teamlist[5] = new team("Inverness Caledonian Thistle","#C01A1A","http://www.football365.com/aberdeen/rss", "https://twitter.com/aberdeenfc","http://www.afc.co.uk/","57�09?33?N�2�05?20?W");`
I need to be able to get the index of an object based on teamname. Ihad thought something along the lines of
var a = teamlist.indexOf(teamname: "Aberdeen");
That however, is obviusly not working.
Any suggestions are welcome - thanks in advance! :)
Simple enough. You can use Array.prototype.some, have the index declared as a variable in lexical scope, and change it when a match occurs. Then return the index. Something like this:
var data = [
{x: '1'},
{x: '2'},
{x: '3'},
{x: '4'}
]; // sample data
function findIndex (num) {
// num is just the number corresponding to the object
// in data array that we have to find
var index = -1; // default value, in case no element is found
data.some(function (el, i){
if (el.x === num) {
index = i;
return true;
}
}); // some will stop iterating the moment we return true
return index;
}
console.log(findIndex('3'));
Hope that helps!
Use this simple index search by value algorithm.
function index_by_value(teamlist, teamname) {
index = 0
for (var i = 0; i < teamlist.length; i++) {
if (teamlist[i].teamname == teamname) {
index = i;
}
}
return index;
}
index = index_by_value(teamlist, "Aberdeen"); // an example
Keep in mind though that if there are multiple objects in the list with the same teamname, it will return the last one's index. If it does not exist, the function will return 0.
You can use filter method:
var a = teamlist.filter(function(team) {
return team.teamname = "Aberdeen";
});
It will produce new array of the teams object with the name of "Aberdeen". If you expect only one team the you need to take the first element from this array: a[0].
function getIndex(teamlist, teamname){
for(var i = 0; i<teamlist.length; i++){
if(teamlist[i].teamname == teamname){
return i; // if found index will return
}
}
return -1; // if not found -1 will return
}
var a = getIndex(teamlist,"Aberdeen"); // will give a as 0

Word frequency for array of key/values on javascript

I'm trying to implement a piece of code on javascript to analyse word/frequency on a given string. My objective is to return a array as the following:
[{text: firstword, size:3 },{text:secondword , size:5 },{text: nword, size: 1},...]
I implemented the following code but I'm running out of memory, so I don't really know if its ok or not.
function wordFrequency(txt){
var wordArray = txt.split(/[ .?!,*'"]/);
var newArray = [];
$.each(wordArray, function (ix, word) {
if (newArray.length >= 1){
newArray.some(function (w){
if (w.text === word){
w.size++;
} else {
newArray.push({text: word, size: 1});
}
});
} else {
newArray.push({text: word, size: 1});
}
});
return newArray;
}
Array.prototype.some expects the given callback to return true or false and returns true as soon as your callback returns true for a given element, otherwise it returns false.
So some iterates over all elements, with your given callback, and your callback checks if the given element text equals the search word and if not adds a new object. Introducing a new element the some function can iterate over.
So to make this clear, for every word thats in the newArray before the word you're searching, you're adding a new object containing your word.
Suppose your newArray looks like this:
[{word:"test"},{word:"another"},{word:"one"},{word:"more"}]
after calling your function for the word even it looks like this:
[{word:"test"},{word:"another"},{word:"one"},{word:"more"},{word:"even"},{word:"even"},{word:"even"},{word:"even"}]
Using Array.prototype.filter would be the better approach here, finding you the matching element, note that I also replaced $.each with Array.prototype.forEach:
function wordFrequency(txt){
var wordArray = txt.split(/[ .?!,*'"]/);
var newArray = [], wordObj;
wordArray.forEach(function (word) {
wordObj = newArray.filter(function (w){
return w.text == word;
});
if (wordObj.length) {
wordObj[0].size += 1;
} else {
newArray.push({text: word, size: 1});
}
});
return newArray;
}
document.write(JSON.stringify(wordFrequency("count everything, count all the words, count all the words!").sort(function(a,b){return a.size<b.size})).split("},").join("}<br/>"));
It would be simpler and far more efficient to create a direct map from word to frequency, and only afterwards convert that to your array structure. Given an array words create a map of the words:
var freq = words.reduce(function(p, c) {
p[c] = (p[c] || 0) + 1;
return p;
}, {});
and the convert that map into your array:
var array = Object.keys(freq).map(function(key) {
return { text: key, size: freq[key] };
});
To tell the frequency all you need is a hash map approach. Your algorithm is quadratic, since the some method is nested in the each method, so you're always looping over the newArray just to find an entry and increment the size.
A map approach is easily achievable using a JavaScript object. It also gives you constant look-up time, which is better performance than the nested loops approach.
Try this approach instead:
function wordFrequency(txt){
var wordArray = txt.split(/[ .?!,*'"]/);
var map = {};
$.each(wordArray, function(ix, word) {
// skip empty results
if (!word.length) {
return;
}
// add word to map
if (!map[word]) {
map[word] = 0;
}
map[word]++;
});
return map;
}
To use the function:
var text = "hello!world*hello foo 'bar'foo";
var result = wordFrequency(text);
// iterate over results
Object.keys(result).forEach(function(w) {
console.log(w + ": " + result[w]);
});
// or use for...in
for (var w in result) {
console.log(w + ": " + result[w]);
}
If you really wanted to, you could then map the result into your desired array format with text and size properties:
var mappedResult = Object.keys(result).map(function(w) {
return { text: w, size: result[w] };
});
console.log(mappedResult);
Also, depending on your target browsers, you might consider using the array forEach instead of the jQuery $.each, similar to what I did with the Object.keys portion.
Here's the JSBin example.
You would probably want to avoid any iterations on duplicate elements and keep your results array unique. Since any of the iterators of Array.prototype will include each of the elements, they might not be the ideal solution for this. Sometimes plain old loops do the job best ...
(You may also want to expressively escape any special characters in your regular expression).
function wordFrequency(txt) {
var words = txt.split(/[ \.\?!,\*'"]+/),
seen = [];
for (var i = 0; i < words.length; i++) {
var w = words[i],
found = false;
for (var j = 0; j < seen.length; j++) {
if (w === seen[j].text) {
seen[j].size++;
found = true;
break;
}
}
if (!found) seen.push( { text: w, size: 1 } );
}
return seen;
}
(Note that the inner for-loop isn't visited for the first word, so the first word will be pushed to the seen-stack and the inner for-loop will start with the second word compared to the first one. Only words that we haven't seen already are added to the seen-stack, making it an array of unique elements.)
And here is the equivalent using Array.prototype.forEach() and Array.prototype.indexOf(), but we have to add another intermediate results stack for the latter one. So we'll have to add another iteration to produce the final result. (We wouldn't have to do this using Array.prototype.findIndex(), but this is not a standard method.)
function wordFrequency2(txt) {
var words = txt.split(/[ \.\?!,\*'"]+/),
seen = [],
freq = [];
// get frequencies
words.forEach(function (w) {
var idx = seen.indexOf(w);
if (idx >= 0) {
freq[idx]++;
}
else {
seen.push(w);
freq.push(1);
}
});
// produce the results array
var r = [];
seen.forEach(function (w, idx) {
r.push( { text: w, size: freq[idx] } );
});
return r;
}
Putting optimization into account, the first version using explicit loops will be probably performing faster ...
var words = (function(){
var sWords = document.body.innerText.toLowerCase().trim().replace(/[,;.]/g,'').split(/[\s\/]+/g).sort();
var iWordsCount = sWords.length; // count w/ duplicates
// array of words to ignore
var ignore = ['and','the','to','a','of','for','as','i','with','it','is','on','that','this','can','in','be','has','if'];
ignore = (function(){
var o = {}; // object prop checking > in array checking
var iCount = ignore.length;
for (var i=0;i<iCount;i++){
o[ignore[i]] = true;
}
return o;
}());
var counts = {}; // object for math
for (var i=0; i<iWordsCount; i++) {
var sWord = sWords[i];
if (!ignore[sWord]) {
counts[sWord] = counts[sWord] || 0;
counts[sWord]++;
}
}
var arr = []; // an array of objects to return
for (sWord in counts) {
arr.push({
text: sWord,
frequency: counts[sWord]
});
}
// sort array by descending frequency | http://stackoverflow.com/a/8837505
return arr.sort(function(a,b){
return (a.frequency > b.frequency) ? -1 : ((a.frequency < b.frequency) ? 1 : 0);
});
}());
(function(){
var iWordsCount = words.length; // count w/o duplicates
for (var i=0; i<iWordsCount; i++) {
var word = words[i];
console.log(word.frequency, word.text);
}
}());

Get full value from array using partial value

I have an array like this:
var array = ["xs-1", "sm-10", "md-4"];
Now I want to get the number at the end of a particular value. For example I want to search the array for "md-" and see what number is at the end of that string (should return 4).
I can't do array.indexOf("xs-") because that isn't the whole value. Is there a way to do this?
Using a for loop:
var array = ["xs-1", "sm-10", "md-4"];
var search = "md-";
var found = null;
for (var i = 0; i < array.length; i++) {
if (array[i].indexOf(search) === 0) {
found = array[i];
break; // Note: this is assuming only one match exists - or at least you are
// only interested in the first match
}
}
if (found) {
alert(found);
} else {
alert("Not found");
}
Using .filter:
var array = ["xs-1", "sm-10", "md-4"];
var search = "md-";
var filtered = array.filter(function(item) {
return item.indexOf(search) === 0;
});
// note that here filtered will contain all matched elements, so it might be more than
// one match.
alert(filtered);
Building from #János Weisz's suggestion, you can easily transform your array into an object using .reduce:
var array = ["xs-1", "sm-10", "md-4"];
var search = "md";
var obj = array.reduce(function(prev, item) {
var cells = item.split("-");
prev[cells[0]] = cells[1];
return prev;
}, {});
// note: at this point we have an object that looks like this:
// { xs:1, sm:10, md: 4 }
// if we save this object, we can do lookups much faster than looping
// through an array
// now to find "md", we simply do:
alert(obj[search]);
If you need to do multiple look ups from the same source array, then transforming it into an object may be the most efficient approach overall. You pay the initial price of the transformation, but after than lookups are O(1) versus O(n) for each time you have to search your array. Of course, if you only ever need one item, then probably don't bother.
I recommend using objects for this:
var array = [{'type': 'xs', 'value': 1}, {'type' : 'sm', 'value': '10'}, {'type' : 'md', 'value': '4'}];
This way you can search the array as:
function searchMyArrayByType(array, type) {
var items[];
for (var i = 0; i < array.length; i++)
{
if (array[i].type == type) items.push(array[i].value);
}
return items;
}
var valuesWithMd = searchMyArrayByType(array, 'md');
For more information regarding the structure and use of objects, please refer to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects
You can create a method that takes the prefix you're looking for, the array, and the split character and returns all the numbers in an array:
function findNumberFromPrefix(prefix, arr, splitChar) {
var values = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i].indexOf(prefix) === 0) {
values.push(arr[i].split(splitChar)[1]);
}
}
return values;
}
And call it:
var array = ["xs-1", "sm-10", "md-4"];
var values = findNumberFromPrefix("md-", array, "-");
console.log(values); //["4"]
Demo: http://jsfiddle.net/rn4h9msh/
A more functional approach and assuming you can have have more than one element with the same prefix:
function findPrefix(array, prefix) {
return array.filter(function (a) { return a.indexOf(prefix) === 0; })
.map(function (e) { return e.slice(prefix.length); })
}
If you have only one matching element, do a loop like this:
var array = ["xs-1", "sm-10", "md-4"];
var needle = "md-";
for(i=0;i<array.length;i++) {
if(array[i].indexOf(needle) == 0)
alert(array[i].substr(needle.length, array[i].length));
}
Demo: http://jsfiddle.net/kg0c43ov/
You can do it like this...
var array = ["xs-1", "sm-10", "md-4"];
getValue("md-");
function getValue(search) {
for(var key in array) {
if(array[key].indexOf(search) > -1) {
alert("Array key is: " + key);
alert("Array value is: " + array[key].replace(search, ""));
}
}
}
JSFiddle here.

Push objects to array so long as object property is not NaN

I am aware that I could use .filter to achieve this, however I am not sure how to implement it.
I have objects as follows within an array
item {
title : g.attributes.title,
category : g.attributes.categoryid,
possible: g.attributes.possible
}
however, some items in the array have a possible property of NaN.
I need to make sure that only items whose possible property is not NaN, are pushed into the array.
Here is an excerpt of my complete code:
function load(id){
itemPath = lev1.lev2.lev3;
items = [];
for (var i = 0; i<itemPath.length; i++) {
if(itemPath[i].attributes.id==id) {
return itemPath[i].attributes.grades.models.map(function(g) {
items.push(
{
title : g.attributes.title,
category : g.attributes.categoryid,
possible: g.attributes.possible
});
});
}
}
}
function load(id){
itemPath = lev1.lev2.lev3;
items = [];
for (var i = 0; i<itemPath.length; i++) {
if(itemPath[i].attributes.id==id) {
return itemPath[i].attributes.grades.models.map(function(g) {
if(g.attributes.possible !== g.attributes.possible){
return;
}
items.push(
{
title : g.attributes.title,
category : g.attributes.categoryid,
possible: g.attributes.possible
});
});
}
}
}
NaN is the only property in javascript that does not equal itself. Just loop over the properties and check them for this, or use the built in NaN() function within the loop as suggested elsewhere.
Update
Since you're only worried about the possible property, just check that one as part of the if statement using === self, or isNaN()
Just change your test line from
if(itemPath[i].attributes.id==id)
to use isNaN function on the properties you want to check
var attr = itemPath[i].attributes;
if (attr.id==id && !isNaN(attr.title) && !isNaN(attr.categoryid) && !isNaN(attr.possible))
You can use the isNaN() and test it before adding it...
function load(id){
itemPath = lev1.lev2.lev3;
items = [];
for (var i = 0; i<itemPath.length; i++) {
if(itemPath[i].attributes.id==id) {
return itemPath[i].attributes.grades.models.map(function(g) {
if( isNaN(g.attributes.title) || isNaN(g.attributes.categoryid) || isNaN(g.attributes.possible) ){
items.push(
{
title : g.attributes.title,
category : g.attributes.categoryid,
possible: g.attributes.possible
});
}
});
}
}
}
You're code is a little confusing
function load(id){
itemPath = lev1.lev2.lev3;
items = [];
for (var i = 0; i<itemPath.length; i++) {
if(itemPath[i].attributes.id==id) {
return itemPath[i].attributes.grades.models.map(function(g) {
items.push(
{
title : g.attributes.title,
category : g.attributes.categoryid,
possible: g.attributes.possible
});
});
}
}
}
It doesn't look like you are using map right. Map works like list compresions in the sense that it iterates over a sequence to preform some kind of operation on each element and returns a new sequence
var arr = [1,2,3];
var complexMagic = arr.map( function(n) { return n + 10; } );
// complexMagic === [11,12,13]
FYI, this is how filter, works. Filter takes in a predicate function( aka, Boolean function) to build a new sequence. If the predicate returns true, then the element will be stored in the new sequence.
var arr = [1, 123, 42, 1001, 1100];
var oddNumbers = arr.filter( function(n) {
return 1 === (n & (-n) );
} );
// oddNumbers === [1, 123, 1001] );
// Bit hacks are fun ;P
It looks like you don't need items array or to even push new elements onto it.
function load(id){
itemPath = lev1.lev2.lev3;
items = [];
for (var i = 0; i<itemPath.length; i++) {
if(itemPath[i].attributes.id==id) {
return itemPath[i].attributes.grades.models.map(function(g) {
// You don't have to return anything.
// This might be an ok place for the NaN check.
return ({
title : g.attributes.title,
category : g.attributes.categoryid,
possible: g.attributes.possible
});
});
}
}
}
I'm lazy and didn't testing any of my code so reader beware. Also avoid the push method if possible. It can be a inefficient approach to append new elements onto an array.

Categories

Resources