Skip to content

Commit 1bbccb6

Browse files
committed
Merge pull request #2105 from jridgewell/indexOf-lastIndexOf-code-sharing
Combine _.indexOf and _.lastIndexOf
2 parents 25bec46 + 9249add commit 1bbccb6

File tree

1 file changed

+35
-36
lines changed

1 file changed

+35
-36
lines changed

underscore.js

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -604,40 +604,8 @@
604604
return result;
605605
};
606606

607-
// Return the position of the first occurrence of an item in an array,
608-
// or -1 if the item is not included in the array.
609-
// If the array is large and already in sort order, pass `true`
610-
// for **isSorted** to use binary search.
611-
_.indexOf = function(array, item, isSorted) {
612-
var i = 0, length = array && array.length;
613-
if (typeof isSorted == 'number') {
614-
i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
615-
} else if (isSorted && length) {
616-
i = _.sortedIndex(array, item);
617-
return array[i] === item ? i : -1;
618-
}
619-
if (item !== item) {
620-
var index = _.findIndex(slice.call(array, i), _.isNaN);
621-
return index >= 0 ? index + i : -1;
622-
}
623-
for (; i < length; i++) if (array[i] === item) return i;
624-
return -1;
625-
};
626-
627-
_.lastIndexOf = function(array, item, from) {
628-
var idx = array ? array.length : 0;
629-
if (typeof from == 'number') {
630-
idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);
631-
}
632-
if (item !== item) {
633-
return _.findLastIndex(slice.call(array, 0, idx), _.isNaN);
634-
}
635-
while (--idx >= 0) if (array[idx] === item) return idx;
636-
return -1;
637-
};
638-
639607
// Generator function to create the findIndex and findLastIndex functions
640-
function createIndexFinder(dir) {
608+
function createPredicateIndexFinder(dir) {
641609
return function(array, predicate, context) {
642610
predicate = cb(predicate, context);
643611
var length = array != null && array.length;
@@ -650,9 +618,8 @@
650618
}
651619

652620
// Returns the first index on an array-like that passes a predicate test
653-
_.findIndex = createIndexFinder(1);
654-
655-
_.findLastIndex = createIndexFinder(-1);
621+
_.findIndex = createPredicateIndexFinder(1);
622+
_.findLastIndex = createPredicateIndexFinder(-1);
656623

657624
// Use a comparator function to figure out the smallest index at which
658625
// an object should be inserted so as to maintain order. Uses binary search.
@@ -667,6 +634,38 @@
667634
return low;
668635
};
669636

637+
// Generator function to create the indexOf and lastIndexOf functions
638+
function createIndexFinder(dir, predicateFind, sortedIndex) {
639+
return function(array, item, idx) {
640+
var i = 0, length = array ? array.length : -1;
641+
if (typeof idx == 'number') {
642+
if (dir > 0) {
643+
i = idx >= 0 ? idx : Math.max(idx + length, i);
644+
} else {
645+
length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
646+
}
647+
} else if (sortedIndex && idx && length) {
648+
idx = _[sortedIndex](array, item);
649+
return array[idx] === item ? idx : -1;
650+
}
651+
if (item !== item) {
652+
idx = _[predicateFind](slice.call(array, i, length), _.isNaN);
653+
return idx >= 0 ? idx + i : -1;
654+
}
655+
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
656+
if (array[idx] === item) return idx;
657+
}
658+
return -1;
659+
};
660+
}
661+
662+
// Return the position of the first occurrence of an item in an array,
663+
// or -1 if the item is not included in the array.
664+
// If the array is large and already in sort order, pass `true`
665+
// for **isSorted** to use binary search.
666+
_.indexOf = createIndexFinder(1, 'findIndex', 'sortedIndex');
667+
_.lastIndexOf = createIndexFinder(-1, 'findLastIndex');
668+
670669
// Generate an integer Array containing an arithmetic progression. A port of
671670
// the native Python `range()` function. See
672671
// [the Python documentation](http://docs.python.org/library/functions.html#range).

0 commit comments

Comments
 (0)