2013-07-11 62 views
1

返回多個外觀使用的indexOf,我可以找到第一次出現的位置:的indexOf類似的功能在JavaScript

例如:

a=[1,2,4,2]; 
b=a.indexOf(2); 
alert(b) //returns 1 

是否有替代功能的indexOf找到這兩個位置還是我錯過了什麼?我正在尋找捷徑。當然,我總是可以寫簡單的外觀來找到它。

回答

2
function indexesOf(arr, target) { 
    // Map matching elements to their index, and others to null. 
    return arr.map(function (el, i) { return (el === target) ? i : null; }) 
      // Throw out the nulls. 
      .filter(function (x) { return x !== null; }); 
} 

alert(indexesOf([1, 2, 4, 2], 2)); // -> 1, 3 
+2

注意:這不會做的是在數組中找到'NaN'的索引,如果這是你需要的函數,所以你需要一個替代的比較方法而不是'===' – Xotic750

+1

@ Xotic750,就像'Array.prototype.indexOf'那樣。 Section [15.4.4.14/9b ii](http://es5.github.io/#x15.4.4.14)表示'indexOf'使用*嚴格相等算法*,它使用NaN相等的通常語義。 –

+0

是的,我只是做了一個筆記,以防有人試圖使用它,然後想知道爲什麼它不起作用。 :) – Xotic750

4

的indexOf需要第二個參數(起始索引)

所以a.indexOf(2,2)會給你3

一概而論,如果x = a.indexOf(2),那麼下一個實例是a.indexOf(2, x+1)

0

lastIndexOf()給出的指數最後一次發生。

但是,如果想要一個索引數組包含特定元素的所有出現(在你的情況下爲2),你必須編寫一個循環。

1

當你正在使用的是最新的ECMAScript 5的方法,那麼你可能要考慮使用Array.mapArray.filter一個新的和諧提出的方法沿着Object.is

的Javascript

var func = {}.is, 
    is; 

if (typeof func === "function") { 
    is = func; 
} else { 
    is = function is(x, y) { 
     if (x === y) { 
      if (x === 0) { 
       return 1/x === 1/y; 
      } 

      return true; 
     } 

     var x1 = x, 
      y1 = y; 

     return x !== x1 && y !== y1; 
    }; 
} 

function indexesOf(array, value) { 
    if (!Array.isArray(array)) { 
     throw new TypeError("First attribute must be an array."); 
    } 

    return array.map(function (element, index) { 
     if (is(value, element)) { 
      return index; 
     } 
    }).filter(function (element) { 
     return typeof element === "number"; 
    }); 
} 

var test = [1, 2, 4, 2]; 

console.log(indexesOf(test, 2)); 

輸出

[1, 3] 

jsfiddle

更新:我已經在過去被詬病爲使用循環時,人有堅強的信念「而這正是這些新方法是專爲」。所以,我也將提出替代單迴路解決方案。

的ECMAScript 5 Array.reduce

的Javascript

function indexesOf(array, value) { 
    if (!Array.isArray(array)) { 
     throw new TypeError("First attribute must be an array."); 
    } 

    return array.reduce(function (previous, current, index) { 
     if (is(value, current)) { 
      previous.push(index); 
     } 

     return previous; 
    }, []); 
} 

jsfiddle

的ECMAScript 5 Array.forEach

的Javascript

function indexesOf(array, value) { 
    if (!Array.isArray(array)) { 
     throw new TypeError("First attribute must be an array."); 
    } 

    var indexes = []; 

    array.forEach(function (element, index) { 
     if (is(value, element)) { 
      indexes.push(index); 
     } 
    }); 

    return indexes. 
} 

jsfiddle

的ECMAScript 5 Array.indexOf

注:此方法是無法找到的指標NaN

也使用Array.lastIndexOf和工作在反向

的Javascript

function indexesOf(array, value) { 
    if (!Array.isArray(array)) { 
     throw new TypeError("First attribute must be an array."); 
    } 

    var index = array.indexOf(value), 
     indexes = []; 

    while (index !== -1) { 
     indexes.push(index); 
     index = array.indexOf(value, index + 1); 
    } 

    return indexes; 
} 

jsfiddle

標準for

的Javascript

function indexesOf(array, value) { 
    if ({}.toString.call(array) !== "[object Array]") { 
     throw new TypeError("First attribute must be an array."); 
    } 

    var indexes = [], 
     length, 
     index; 

    for (index = 0, length = array.length; index < length; index += 1) { 
     if (array.hasOwnProperty(index) && is(value, array[index])) { 
      indexes.push(index); 
     } 
    } 

    return indexes; 
} 

jsfiddle

標準while

的Javascript

function indexesOf(array, value) { 
    if ({}.toString.call(array) !== "[object Array]") { 
     throw new TypeError("First attribute must be an array."); 
    } 

    var length = array.length, 
     indexes = [] 
     index = 0; 

    while (index < length) { 
     if (array.hasOwnProperty(index) && is(value, array[index])) { 
      indexes.push(index); 
     } 

     index += 1; 
    } 

    return indexes; 
} 

jsfiddle

標準for...in

注:不建議這樣做,但應該罰款。

Why is using 「for…in」 with array iteration such a bad idea?

的Javascript

function indexesOf(array, value) { 
    if ({}.toString.call(array) !== "[object Array]") { 
     throw new TypeError("First attribute must be an array."); 
    } 

    var indexes = [], 
     prop; 

    for (prop in array) { 
     if (array.hasOwnProperty(prop) && is(+prop, prop >>> 0) && is(value, array[prop])) { 
      indexes.push(+prop); 
     } 
    } 

    return indexes; 
} 

jsfiddle

注:所有的解決方案在這裏同時處理密集和稀疏的陣列。

最後一個jsperf比較所有這些解決方案。

+2

這真是一個很好的替代答案。我也想知道downvote的原因。 –