How do I make Array.indexOf() case insensitive?

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>
104716 次浏览

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.

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

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

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();

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
}

ES2015 findIndex:

var 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

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
}
}

More info

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:');
}

This is the shortest one.

haystack.join(' ').toLowerCase().split(' ').indexOf(needle.toLowerCase())

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.

You can use Array.prototype.find()

found = 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.

// unique only, removes latter occurrences
array.filter((v, i, a) => a.findIndex(j => v.toLowerCase() === j.toLowerCase()) === i);

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 ));