How do I make Array.indexOf() case insensitive?
JavascriptJavascript Problem Overview
I am making a piece of code for a website that will have a list of names in an array and pick a random name, I want to add a feature that will let the user add or delete a name from the array. I have all of these features but when deleting a name, the user has to type the name to match the Case in the array. I tried to make the so it would be Case-Insensitive, what am I doing wrong?
<html>
<!--Other code uneeded for this question-->
<p id="canidates"></p>
<body>
<input type="text" id="delname" /><button onclick="delName()">Remove Name from List</button>
<script>
//Array of names
var names = [];
//Other code uneeded for this question
//List of Canidates
document.getElementById('canidates').innerHTML =
"<strong>List of Canidates:</strong> " + names.join(" | ");
//Other code uneeded for this question
//Remove name from Array
function delName() {
var dnameVal = document.getElementById('delname').value;
var pos = names.indexOf(dnameVal);
var namepos = names[pos]
var posstr = namepos.toUpperCase();
var dup = dnameVal.toUpperCase();
if(dup != posstr) {
alert("Not a valid name");
}
else {
names.splice(pos, 1);
document.getElementById('canidates').innerHTML =
"<strong>List of Canidates:</strong> " + names.join(" | ");
}
}
</script>
</body>
</html>
Javascript Solutions
Solution 1 - Javascript
findIndex:
ES2015var array = ['I', 'hAve', 'theSe', 'ITEMs'],
indexOf = (arr, q) => arr.findIndex(item => q.toLowerCase() === item.toLowerCase());
console.log( indexOf(array, 'i') ) // 0
console.log( indexOf(array, 'these') ) // 2
console.log( indexOf(array, 'items') ) // 3
Solution 2 - Javascript
In ECMA-262, 5th edition, you could use Array.prototype.some
for this.
var array = [ 'I', 'hAve', 'theSe', 'ITEMs' ];
var query = 'these'.toLowerCase();
var index = -1;
array.some(function(element, i) {
if (query === element.toLowerCase()) {
index = i;
return true;
}
});
// Result: index = 2
Solution 3 - Javascript
Easy way would be to have a temporary array that contains all the names in uppercase. Then you can compare the user input. So your code could become somthing like this:
function delName() {
var dnameVal = document.getElementById('delname').value;
var upperCaseNames = names.map(function(value) {
return value.toUpperCase();
});
var pos = upperCaseNames.indexOf(dnameVal.toUpperCase());
if(pos === -1) {
alert("Not a valid name");
}
else {
names.splice(pos, 1);
document.getElementById('canidates').innerHTML =
"<strong>List of Canidates:</strong> " + names.join(" | ");
}
}
Hope this helps solve your problem.
Solution 4 - Javascript
The most elegant solution would be to convert the array into a string first, then do a case insensitive comparison. For example:
var needle = "PearS"
var haystack = ["Apple", "banNnas", "pEArs"];
var stricmp = haystack.toString().toLowerCase(); // returns
// "apple,bananas,pears"
if (stricmp.indexOf(needle.toLowerCase()) > -1) {
// the search term was found in the array
} else {
// the search term was not found in the array
}
Solution 5 - Javascript
Probably best to create your own custom indexOf
method, something like this.
'use strict';
var customIndexOf = function(arrayLike, searchElement) {
var object = Object(arrayLike);
var length = object.length >>> 0;
var fromIndex = arguments.length > 2 ? arguments[2] >> 0 : 0;
if (length < 1 || typeof searchElement !== 'string' || fromIndex >= length) {
return -1;
}
if (fromIndex < 0) {
fromIndex = Math.max(length - Math.abs(fromIndex), 0);
}
var search = searchElement.toLowerCase();
for (var index = fromIndex; index < length; index += 1) {
if (index in object) {
var item = object[index];
if (typeof item === 'string' && search === item.toLowerCase()) {
return index;
}
}
}
return -1;
};
var names = [
'John',
'Anne',
'Brian'
];
console.log(customIndexOf(names, 'aNnE'));
Or even
'use strict';
var customIndexOf = function(array, searchElement, fromIndex) {
return array.map(function(value) {
return value.toLowerCase();
}).indexOf(searchElement.toLowerCase(), fromIndex);
};
var names = [
'John',
'Anne',
'Brian'
];
console.log(customIndexOf(names, 'aNnE'));
You may also want to add more checks to be sure that each element in the array is actually a String
and that the searchElement
is also actually a String
too. If pre-ES5 then load appropriate shims
Solution 6 - Javascript
Array.prototype.find()
You can usefound = myArray.find(key => key.toUpperCase() === searchString.toUpperCase()) != undefined;
Example:
myArray = ['An', 'aRRay', 'oF', 'StringS'];
searchString = 'array';
found = myArray.find(key => key.toUpperCase() === searchString.toUpperCase()) != undefined;
if (found ) {
// The array contains the search string
}
else {
// Search string not found
}
Note: Array cannot contain undefined
as a value.
Solution 7 - Javascript
It is possible using by map method. For example see below code
var _name = ['prasho','abraham','sam','anna']
var _list = [{name:'prasho'},{name:'Gorge'}];
for(var i=0;i<_list.length;i++)
{
if(_name.map(function (c) {
return c.toLowerCase();
}).indexOf(_list[i].name.toLowerCase()) != -1) {
//do what ever
}else{
//do what ever
}
}
Solution 8 - Javascript
I needed something similar to this where I needed compare two strings using includes
and needed to be able to support both case and case insensitive searches so I wrote the following small function
function compare(l1: string, l2: string, ignoreCase = true): boolean {
return (ignoreCase ? l1.toLowerCase() : l1).includes((ignoreCase ? l2.toLowerCase() : l2));
}
Same principle could apply to indexOf
as below
function indexOf(l1: string, l2: string, ignoreCase = true): number {
return (ignoreCase ? l1.toLowerCase() : l1).indexOf((ignoreCase ? l2.toLowerCase() : l2));
}
I know this is not specifically Array.indexOf
but hope this helps someone out if the come across this post on their travels.
To answer the ops question though, you can apply this similarly to an array combined with this answer from @ULIT JAIDEE (the slight change to this was using the tilda character as a separator in case any of the array values contained spaces)
function compare(l1: any[], l2: any[], ignoreCase = true): boolean {
return (ignoreCase ? l1.join('~').toLowerCase().split('~') : l1).indexOf((ignoreCase ? l2.join('~').toLowerCase().split('~') : l2));
}
Again hope this helps.
Solution 9 - Javascript
Turn the array into a string separated by a delimiter, turn that string lowercase, and then split the string back into an array by the same delimiter:
function findIt(arr, find, del) {
if (!del) { del = '_//_'; }
arr = arr.join(del).toLowerCase().split(del);
return arr.indexOf(find.toLowerCase());
}
var arr = ['Tom Riddle', 'Ron Weasley', 'Harry Potter', 'Hermione Granger'];
var find = 'HaRrY PoTtEr';
var index = findIt(arr, find);
if (~index) {
alert('Found ' + arr[index] + '! :D');
} else {
alert('Did not find it. D:');
}
Solution 10 - Javascript
This is the shortest one.
haystack.join(' ').toLowerCase().split(' ').indexOf(needle.toLowerCase())
Solution 11 - Javascript
// unique only, removes latter occurrences
array.filter((v, i, a) => a.findIndex(j => v.toLowerCase() === j.toLowerCase()) === i);
Solution 12 - Javascript
To improve on @vsync answer and handle mixed content in the array here is my take. (I understand the OP is about case-sensitive thus it implies strings, maybe :)
var array = ['I', 'hAve', 7, {}, 'theSe', 'ITEMs'],
Contains = (arr, q) =>
arr.findIndex((item) => q.toString().toLowerCase() === item.toString().toLowerCase());
console.log(Contains(array, 'i'));
console.log(Contains(array, 'x'));
console.log(Contains(array, {} ));
console.log(Contains(array, 7 ));
Solution 13 - Javascript
You can't make it case-insensitive. I'd use an object instead to hold a set of names:
function Names() {
this.names = {};
this.getKey = function(name) {
return name.toLowerCase();
}
this.add = function(name) {
this.names[this.getKey(name)] = name;
}
this.remove = function(name) {
var key = this.getKey(name);
if (key in this.names) {
delete this.names[key];
} else {
throw Error('Name does not exist');
}
}
this.toString = function() {
var names = [];
for (var key in this.names) {
names.push(this.names[key]);
}
return names.join(' | ');
}
}
var names = new Names();
function update() {
document.getElementById('canidates').innerHTML = '<strong>List of Canidates:</strong> ' + names;
}
function deleteName() {
var name = document.getElementById('delname').value;
try {
names.remove(name);
update();
} catch {
alert('Not a valid name');
}
}
update();