From d2d6cfe6675d18b058e52785c438a3c1a7502208 Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Fri, 17 Dec 2010 10:57:12 -0500 Subject: [PATCH] Rework of #68, to use a flag to indexOf, instead of a separate function. --- index.html | 20 ++++---------------- test/arrays.js | 12 ++++++++++++ test/collections.js | 14 -------------- underscore.js | 18 +++++++----------- 4 files changed, 23 insertions(+), 41 deletions(-) diff --git a/index.html b/index.html index 23a1d47dd..9be2ba75d 100644 --- a/index.html +++ b/index.html @@ -142,7 +142,6 @@

Table of Contents

invoke, pluck, max, min, sortBy, sortedIndex, - sortedIndexOf, toArray, size

@@ -453,19 +452,6 @@

Collection Functions (Arrays or Objects)

 _.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
 

@@ -599,11 +585,13 @@

Array Functions

- indexOf_.indexOf(array, value) + indexOf_.indexOf(array, value, [isSorted])
Returns the index at which value can be found in the array, or -1 if value is not present in the array. Uses the native - indexOf function unless it's missing. + indexOf function unless it's missing. If you're working with a + large array, and you know that the array is already sorted, pass true + for isSorted to use a faster binary search.

 _.indexOf([1, 2, 3], 2);
diff --git a/test/arrays.js b/test/arrays.js
index c7553fc57..7219c038e 100644
--- a/test/arrays.js
+++ b/test/arrays.js
@@ -84,6 +84,18 @@ $(document).ready(function() {
     var result = (function(){ return _.indexOf(arguments, 2); })(1, 2, 3);
     equals(result, 1, 'works on an arguments object');
     equals(_.indexOf(null, 2), -1, 'handles nulls properly');
+
+    var numbers = [10, 20, 30, 40, 50], num = 35;
+    var index = _.indexOf(numbers, num, true);
+    equals(index, -1, '35 is not in the list');
+
+    numbers = [10, 20, 30, 40, 50]; num = 40;
+    index = _.indexOf(numbers, num, true);
+    equals(index, 3, '40 is in the list');
+
+    numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40;
+    index = _.indexOf(numbers, num, true);
+    equals(index, 1, '40 is in the list');
   });
 
   test("arrays: lastIndexOf", function() {
diff --git a/test/collections.js b/test/collections.js
index 6c0e8830c..442b205f1 100644
--- a/test/collections.js
+++ b/test/collections.js
@@ -185,20 +185,6 @@ $(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 4d0851935..cf11afb5f 100644
--- a/underscore.js
+++ b/underscore.js
@@ -254,8 +254,6 @@
 
   // 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;
@@ -266,14 +264,6 @@
     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 [];
@@ -366,8 +356,14 @@
   // we need this function. Return the position of the first occurrence of an
   // item in an array, or -1 if the item is not included in the array.
   // Delegates to **ECMAScript 5**'s native `indexOf` if available.
-  _.indexOf = function(array, item) {
+  // If the array is large and already in sort order, pass `true`
+  // for **isSorted** to use binary search.
+  _.indexOf = function(array, item, isSorted) {
     if (array == null) return -1;
+    if (isSorted) {
+      var i = _.sortedIndex(array, item);
+      return array[i] === item ? i : -1;
+    }
     if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
     for (var i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
     return -1;