I have a dictionary like:
a = {"staticData":['----','Blue','Green'], "inData":['Indatahere','----','----']}
How can I find that if the dictionary contains "----", in any of the key's values.
Any Javascript function?
EDIT:
What if the case is like this?
a = {"staticData":[], "inData":['Indatahere','----','----']}
It's giving this Error:
TypeError: a[elem].indexOf is not a function
Here is the code:
var a = {"staticData":['----','Blue','Green'], "inData":['Indatahere','----','----']};
for(var key in a){
var value = a[key];
for(var i=0; i<value.length; i++){
if(value[i] == '----') alert("Found '----' in '" + key + "' at index " + i);
};
}
EDIT: Changed iteration over array to normal way after comment.
Use indexOf to search each array in the a object:
for (elem in a)
{
if (a[elem].indexOf("----") != -1)
alert('---- found at ' + a[elem]);
}
EDIT
For this error: TypeError: a[elem].indexOf is not a function the browser possibly considers an empty element to be a non-string type; non-string type does not have an indexOf method.
This code checks the length of the array element (if the element is empty before interpreting the indexOf function.
for (elem in a)
{
if (a[elem].length > 0 && a[elem].indexOf("----") != -1)
alert('---- found at ' + a[elem]);
}
If you wish to support IE < 9, see this post to conditionally add a indexOf definition to the Array object. The post also mentions a Jquery alternative.
The SO post mentioned above lists this Mozilla version of indexOf function.
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(elt /*, from*/)
{
var len = this.length >>> 0;
var from = Number(arguments[1]) || 0;
from = (from < 0)
? Math.ceil(from)
: Math.floor(from);
if (from < 0)
from += len;
for (; from < len; from++)
{
if (from in this &&
this[from] === elt)
return from;
}
return -1;
};
}
If you know exactly the nesting level of your value, then a quick solution (as suggested in other answers) is possible.
However, if you need a deep traversal search, you're gonna need a recursive version of the solutions, something like:
function FindTraverse(data, match)
{
for (var prop in data)
{
if (!data.hasOwnProperty(prop)) continue;
if (data[prop] == match) return true;
if (typeof data[prop] == 'object' && FindTraverse(data[prop], match)) return true;
}
return false;
}
Examples:
FindTraverse({a:'Foo',b:'Bar'}, 'Bar') // true
FindTraverse(['Foo','Bar'], 'Bar') // true
FindTraverse([{name:'Foo'},{name:'Bar'}], 'Bar') // true
FindTraverse({a:{name:'FooBar'},b:'Bar'}, 'FooBar') // true
However, if you're looking for a more thorough solution, use a framework like jsTraverse
Use Object.getOwnPropertyNames().
You have to write two nested loops. With Object.getOwnPropertyNames you are accessing an array which consists of property names of an object. You will then need to loop over the value of those properties and identify the correct element within this second array.
a = {"staticData":['----','Blue','Green'], "inData":['Indatahere','----','----']}
props = Object.getOwnPropertyNames(a);
for (i=0;i < props.length;i ++) {
for (z = 0; z < a[props[i]].length; z ++) {
//console.log(a[props[i]][z])
if ( (a[props[i]][z]) == '----') {
console.log("I have found an item with ----")
};
}
}
Related
For example:
var array = [1,2,3,4];
if( 5 > array ){
alert('ok');
}
Can i do this in javascript ?
Well, it's pretty simple, use .indexOf() (MDN)
var text ="abc";
var array = ['abc', 'def'];
if(array.indexOf(text) !== -1){
alert('ok');
}
Can I do this in JavaScript?
I don't know. Try it.
An if statement evaluates a single expression. If you want to evaluate multiple conditions, which is the case here, you have to write the multiple conditions.
if( 5 > array[0] && 5 > array[1] && 5 > array[2] && 5 > array[3]) {
alert('ok');
}
Since that is not going to work well if you don't know the number of elements in array in advance, you could write a loop, looking for failing cases:
let ok = true;
for (const i = 0; i < array.length; i++) {
if (5 > array[i]) continue;
ok = false;
break;
}
if (ok) alert('ok');
It turns out, though, that arrays have a built-in method to check to see if some condition holds for all elements, so we can write:
if (array.every(elt => 5 > elt)) alert('ok');
If you wanted to check if an element(text) exists in the array, then this can be used
if(array.indexOf(text) !== -1){
alert('ok');
}
var array = [1,2,3,4,5]
var i = 0;
var num = 4;
for(i = 0;i < array.length;i++){
if(array[i] == num){
alert("OK")
}
}
This can also be used but using the indexOf() function will be much faster
Since I had to remove some elements from my arrays, I followed a few pieces of code found in stackoverflow and came up with this one:
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
For some reasons, however, this piece of code is being printed EVERYWHERE whenever something has something to with an array.
Example:
this piece of code:
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
Scadenza.prototype.init = function() {
this.promemoria = (this.promemoria == "")?("NO"):(this.promemoria);
var gruppo = this.group; // convert array to string.
this.group = "";
for (var i in gruppo) {
if (i != (gruppo.length - 1)) {
this.group += gruppo[i] + ", ";
}
else {
this.group += gruppo[i];
}
}
alert(this.group);
};
This piece of code is supposed to convert the array this.group (stored temporarily in the variable "gruppo") into a string (that's quite obvious, I think).
It is, of course, doing it's job greatly, if it wouldn't be that its alert is:
[DATA NEEDED]function (from, to) { var rest = this.slice((to || from)
+ 1 || this.length); this.length = from < 0 ? this.length + from : from; return this.push.apply(this, rest); }
This piece of code is being also sent to a database through an AJAX request and the result of the query, at the desired coloumn, is this one:
function (from, to) { var rest = this.slice((to || from) + 1 ||
this.length); this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest); },
I'm quite surprised this is happening but I have ABSOLUTELY no idea on how to fix it.
No errors have been alerted while loading the page or when clicking the button that throws this event.
Any idea?
ps: Not sure if helps, but I'm using jQuery.
#comments:
The normal for loop actually doesn't fix this:
Scadenza.prototype.init = function() {
this.promemoria = (this.promemoria == "")?("NO"):(this.promemoria);
var gruppo = this.group; // convert array to string.
this.group = "";
for (var i = 0; i < gruppo.length; i++) {
if (i != (gruppo.length - 1)) {
this.group += gruppo[i] + ", ";
}
else {
this.group += gruppo[i];
}
}
alert(this.group);
};
Alert is still the same.
Use proper for (var i=0; i<arr.length; i++) loops for iterating arrays. for in enumerations will enumerate prototype properties as well, do not use them on arrays. You are doing that in your init method for example.
Btw, for that task you want to use .join anyway:
Scadenza.prototype.init = function() {
if (this.promemoria == "")
this.promemoria = "NO";
this.group = this.group.join(", "); // convert array to string
alert(this.group);
};
When you change the Array prototype, the method is added to the Array object as a new attribute. When you iterate with for (var attr in object) you are iterating over the object and all of its attributes. Therefore, your new method is included in that loop.
You need to use a for (var i=0; i<a.length; i++) loop. That will only include items in the array.
Other browsers work fine but in IE i get Number Expected when using the following code and it runs into a null object on the sort function.
http://jsfiddle.net/R3ndd/2/
function list_response(jsonData) {
"use strict";
var lists = document.getElementById("lists"), anchors = document.getElementById("anchors"), jItems = jsonData.items;
var results = [], anks = [], vList, pListName, item, videoItem;
var i, j, jLen, iLen = jItems.length;
for (var i = 0; i < iLen; i++) {
if(jItems[i] != null ){
jItems[i].nameLower = jItems[i].name.toLowerCase();
}
}
jItems.sort(function (a, b) {
if(a != null && b != null){
return a.nameLower.localeCompare(b.nameLower);
}
});
Any suggestions? Thanks!
My Solution
I decided to remove the null object (which works) from json using the following:
var y;
for (var x in jItems) {
if ( Object.prototype.hasOwnProperty.call(jItems,x)) {
y = jItems[x];
if (y==="null" || y===null || y==="" || typeof y === "undefined") {
delete jItems[x];
}
}
}
Don't know why IE does that, but it is it's habit to trouble us good people :). Well, I think this will be better way.
/* NOT NEEDED.
for (var i = 0; i < iLen; i++) {
if(jItems[i] != null ){
jItems[i].nameLower = jItems[i].name.toLowerCase();
}
}*/
jItems.sort(function (a, b) {
return a && b ? a.toLowerCase().localeCompare(b.toLowerCase()) : 0;
});
UPDATE:
Well, I think I know where IE is troubling. Sorry MS, this time IE hasn't any fault. What happened was that in case where either a or b were null/''/false (or any falsy value), your callback didn't return any value. That explians the 'Number expected' error. But I took care of that, so my answer will probably work. :)
I am trying to edit the jQuery hightlight plug in to highlight multiple words. It works great until you hit the space bar, then it causes FF to freeze in an infinite loop.
FireBug reports that .toUpperCase is not a function, but when I change the same code back, so it is not altering an array element, it's fine, but does not highlight the two words, only the first one. When the space bar is hit all highlighting goes away.
Here is the what I have so far. The code in question is in the return this.each(function(){}) block at the end:
jQuery.fn.highlight = function(pat) {
function innerHighlight(node, pat) {
var skip = 0;
if (node.nodeType == 3) {
var pos = node.data.toUpperCase().indexOf(pat);
if (pos >= 0) {
var spannode = document.createElement('span');
spannode.className = 'highlight';
var middlebit = node.splitText(pos);
var endbit = middlebit.splitText(pat.length);
var middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode, middlebit);
skip = 1;
}
} else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
for (var i = 0; i < node.childNodes.length; ++i) {
i += innerHighlight(node.childNodes[i], pat);
}
}
return skip;
}
return this.each(function() {
var parts = pat.split(' ');
console.log(parts);
for (var i in parts) {
innerHighlight(this, parts[i].toUpperCase());
console.log("parts["+i+"] >> " + parts[i]);
}
});
};
Here is the console output in FireBug:
["guy"] jquery...ht-3.js (line 46)
parts[0] >> guy jquery...ht-3.js (line 49)
parts[i].toUpperCase is not a function
[Break On This Error] innerHighlight(this, parts[i].toUpperCase());
jquery...ht-3.js (line 48)
any help would be greatly appreciated!
Oh dear. That plugin is using an unfiltered for...in loop to iterate over an array. That's bad:
for...in should not be used to iterate over an Array where index
order is important. Array indexes are just enumerable properties with
integer names and are otherwise identical to general Object
properties. There is no guarantee that for...in will return the
indexes in any particular order and it will return all enumerable
properties, including those with non–integer names and those that are
inherited.
Because the order of iteration is implementation dependent, iterating
over an array may not visit elements in a consistent order. Therefore
it is better to use a for loop with a numeric index when iterating
over arrays where the order of access is important.
Where only the properties of the object should be considered, a
hasOwnProperty check should be performed to ensure that only
properties of the object and not inherited properties are used
(propertyIsEnumerable can also be used but is not intuitive).
So, change this:
for (var i in parts) {
innerHighlight(this, parts[i].toUpperCase());
console.log("parts["+i+"] >> " + parts[i]);
}
to this:
for (var i=0; i<parts.length; i++) {
innerHighlight(this, parts[i].toUpperCase());
console.log("parts["+i+"] >> " + parts[i]);
}
I have a list like
_Value1 = "'apple','ball','cat'....so on";
If I know that apple exists in above list.How to get index of whole string from the list.Like apple should have the index 1, ball should have 2 and so on.
What is the javascript code for this stuff?
var _Value1 = "'apple','ball','cat'";
// split the string on ","
var values = _Value1.split(",");
// call the indexOf method
var index = values.indexOf("'apple'");
working example: http://jsfiddle.net/Yt5fp/
You can also do this check if it is an older browser and add the indexOf method if it doesn't exist
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(elt /*, from*/) {
var len = this.length;
var from = Number(arguments[1]) || 0;
from = (from < 0) ? Math.ceil(from) : Math.floor(from);
if (from < 0) from += len;
for (; from < len; from++) {
if (from in this && this[from] === elt) return from;
}
return -1;
};
}
Try using this trick:
_Array = eval("[" + _Value1 + "]");
(It will create object of array using JSON)
Assuming your strings (apple, ball, cat...) will not have a , in them:
You can split a string based on a delimiter:
var split = _values.split(",")
You will get an array of strings: {'apple', 'ball', 'cat'}
You can use the indexOf method in the array to find the position of an element:
split.indexOf('apple')
indexOf is not supported by IE. You can use the alternative in How to fix Array indexOf() in JavaScript for Internet Explorer browsers