26

I am trying to find if an image has in its source name noPic which can be in upper or lower case.

var noPic = largeSrc.indexOf("nopic");

Should I write :

var noPic = largeSrc.toLowerCase().indexOf("nopic");

But this solution doesn't work...

Mamun
  • 58,653
  • 9
  • 33
  • 46
adardesign
  • 29,076
  • 14
  • 59
  • 80
  • What is largeSrc? Are you sure it is a string? – Josh Stodola Aug 07 '09 at 18:09
  • 1
    Use the debugger. Set a breakpoint on the `var noPic = ...` line and see what the type and value of `largeSrc` are. Or you can put a `console.log( typeof largeSrc, largeSrc );` before your line. But from the question, it sounds like you may not be familiar with the interactive JavaScript debugger in your browser. I highly recommend getting familiar with it. For example: [Chrome DevTools tutorial](https://developer.chrome.com/devtools). – Michael Geary Jan 01 '18 at 05:24

5 Answers5

29

You can use regex with a case-insensitive modifier - admittedly not necessarily as fast as indexOf.

var noPic = largeSrc.search(/nopic/i);
jharlap
  • 788
  • 6
  • 5
  • 8
    According to: http://jsperf.com/regex-vs-tolowercase-then-regex/2 the regex method is faster than toLower() – Mike McKay Apr 22 '12 at 04:34
  • 1
    the regex method ends up being slower if the search term comes from user input, see my answer here http://stackoverflow.com/a/19920595/1333402 – ssmith Nov 12 '13 at 03:59
  • @ppumkin It will if you need to do this in a tight loop. – simonzack Aug 29 '14 at 21:04
  • I'm curious as to why, though, his initial method did not work. – Dandy Oct 28 '14 at 14:28
  • 2
    Up until Chrome 64, the regex approach might have held its own, but as of 69, `toLowerCase()` is 31 times faster, according to http://jsperf.com/regex-vs-tolowercase-then-regex/2. – jdunning Oct 27 '18 at 02:34
  • ppumkin Not sure if that's a hypothetical 50ms, but it's going to be far less than that even. The perf linked to by Mike is showing an incredible difference, but in my environment it was 7M operations per second vs. 347M operations per second. It's theoretically a HUGE difference in performance; however, I agree with what you're driving at: "You mean I can still do this 7 million times in a second? I think I'm OK." Especially if it's client side rather than having to scale to large numbers of connections server-side. – Greg Pettit Jan 24 '19 at 17:42
19

No, there is no case-insensitive way to call that function. Perhaps the reason your second example doesn't work is because you are missing a call to the text() function.

Try this:

var search = "nopic";
var noPic = largeSrc.text().toLowerCase().indexOf(search.toLowerCase());
Community
  • 1
  • 1
Andrew Hare
  • 320,708
  • 66
  • 621
  • 623
  • 3
    note that indexOf() can be slow for large strings, see http://stackoverflow.com/a/4579228/1333402 – ssmith Nov 12 '13 at 04:02
5

Note that if the search string is from user input you'll need to escape the special regexp characters.

Here's what it would look like:

var search = getUserInput();

/* case-insensitive search takes around 2 times more than simple indexOf() */
var regex = RegExp(search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), "i");

var noPic = testString.search(regex);

See the updated jsperf: http://jsperf.com/regex-vs-tolowercase-then-regex/4

footnote: regexp escaping from https://stackoverflow.com/a/3561711/1333402

Klesun
  • 7,746
  • 5
  • 37
  • 41
ssmith
  • 634
  • 7
  • 10
  • I edited out the part where you were saying that escaped regex makes search slower than `toLowerCase()` as I believe this is the one right solution and I have the data confirming that regex search actually scales much more efficiently than `toLowerCase()`. In my use case it was 100 MiB long text and around 20 characters lookup substring: `toLowerCase()` call alone took more than a second of CPU time, while direct regex search ran withing 30 ms, that's just slighty longer than a regular `indexOf()`. – Klesun Oct 26 '20 at 20:46
3

Try with:

var lowerCaseLargeSrc = largeSrc.toLowerCase();
var noPic = lowerCaseLargeSrc.indexOf("nopic");
Lupus Ossorum
  • 428
  • 2
  • 16
1

Your code will only work if largeSrc is already a string. You might be getting an input that's an html element instead. So, use jQuery to resolve any potential input element into the text that's inside it. Example:

var noPic = largeSrc.text().toLowerCase().indexOf("nopic");
Barett
  • 5,226
  • 6
  • 46
  • 53
bylerj
  • 93
  • 5