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])
Uses a binary search to determine the index at which the value - should be inserted into the list in order to maintain the list's + should be inserted into the list in order to maintain the list's sorted order. If an iterator is passed, it will be used to compute the sort ranking of each value.

 _.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 [];