diff --git a/index.html b/index.html index e94751446..23a1d47dd 100644 --- a/index.html +++ b/index.html @@ -142,6 +142,7 @@ invoke, pluck, max, min, sortBy, sortedIndex, + sortedIndexOf, toArray, size
@@ -445,13 +446,26 @@ _.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); }); sortedIndex_.sortedIndex(list, value, [iterator])
_.sortedIndex([10, 20, 30, 40, 50], 35); => 3 ++ +
+ sortedIndexOf_.sortedIndexOf(list, value)
+
+ Not to be confused with _.sortedIndex, this method works like
+ the native indexOf, but uses binary search to efficiently
+ find the value in large, already-sorted arrays. Returns -1
+ if the value is not present.
+
+_.sortedIndex([10, 20, 30, 40, 50], 30); +=> 2
diff --git a/test/collections.js b/test/collections.js index 442b205f1..6c0e8830c 100644 --- a/test/collections.js +++ b/test/collections.js @@ -185,6 +185,20 @@ $(document).ready(function() { equals(index, 3, '35 should be inserted at index 3'); }); + test('collections: sortedIndexOf', function() { + var numbers = [10, 20, 30, 40, 50], num = 35; + var index = _.sortedIndexOf(numbers, num); + equals(index, -1, '35 is not in the list'); + + numbers = [10, 20, 30, 40, 50]; num = 40; + index = _.sortedIndexOf(numbers, num); + equals(index, 3, '40 is in the list'); + + numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40; + index = _.sortedIndexOf(numbers, num); + equals(index, 1, '40 is in the list'); + }); + test('collections: toArray', function() { ok(!_.isArray(arguments), 'arguments object is not an array'); ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array'); diff --git a/underscore.js b/underscore.js index 6cb2527dd..4d0851935 100644 --- a/underscore.js +++ b/underscore.js @@ -254,6 +254,8 @@ // Use a comparator function to figure out at what index an object should // be inserted so as to maintain order. Uses binary search. + // Unlike `_.sortedIndexOf`, this function returns the array at which an + // element *should* be inserted, not where it actually is. _.sortedIndex = function(array, obj, iterator) { iterator = iterator || _.identity; var low = 0, high = array.length; @@ -264,6 +266,14 @@ return low; }; + // Similar to native `indexOf`, but assumes that the array being searched + // is already sorted, giving much faster performance on large arrays. + // Not to be confused with `_.sortedIndex`. + _.sortedIndexOf = function(array, obj) { + var i = _.sortedIndex(array, obj); + return array[i] === obj ? i : -1; + }; + // Safely convert anything iterable into a real, live array. _.toArray = function(iterable) { if (!iterable) return [];