Сподіваємось, швидший двосторонній indexOf
/ lastIndexOf
альтернативний варіант
2015 рік
Незважаючи на те, що новий метод включає дуже приємно, підтримка в даний час в основному дорівнює нулю.
Давно я думав над способом замінити повільні функції indexOf / lastIndexOf.
Виконаний шлях уже знайдено, дивлячись на відповіді вгорі. З тих, кого я вибравcontains
функцію, яку опублікував @Damir Zekic, яка повинна бути найшвидшою. Але також зазначено, що орієнтири є з 2008 року і тому застаріли.
Я також віддаю перевагу while
над for
, але з не певної причини я закінчив писати функцію циклом for. Це також можна зробити з awhile --
.
Мені було цікаво, чи ітерація була набагато повільнішою, якщо я перевіряю обидві сторони масиву, роблячи це. Мабуть, ні, і тому ця функція приблизно в два рази швидша, ніж голосові вгорі. Очевидно, він також швидший, ніж рідний. Це в реальному світі, коли ви ніколи не знаєте, чи є значення, яке ви шукаєте, на початку або в кінці масиву.
Коли ви знаєте, що ви просто натиснули масив зі значенням, використання lastIndexOf залишається, ймовірно, найкращим рішенням, але якщо вам доведеться подорожувати великими масивами, і результат може бути скрізь, це може бути надійним рішенням, щоб зробити справи швидшими.
Двонаправлений indexOf / lastIndexOf
function bidirectionalIndexOf(a, b, c, d, e){
for(c=a.length,d=c*1; c--; ){
if(a[c]==b) return c; //or this[c]===b
if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
}
return -1
}
//Usage
bidirectionalIndexOf(array,'value');
Тест на продуктивність
http://jsperf.com/bidirectionalindexof
Як тест я створив масив із 100k записів.
Три запити: на початку, в середині та в кінці масиву.
Я сподіваюся, що ви також знайдете це цікавим і випробуєте виступ.
Примітка. Як ви бачите, я трохи змінив contains
функцію, щоб відображати вихід indexOf & lastIndexOf (так це в основному true
з index
і false
з -1
). Це не повинно завдати шкоди.
Варіант прототипу масиву
Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
for(c=this.length,d=c*1; c--; ){
if(this[c]==b) return c; //or this[c]===b
if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
}
return -1
},writable:false, enumerable:false});
// Usage
array.bidirectionalIndexOf('value');
Функцію також можна легко змінити, щоб повернути істинне чи помилкове або навіть об'єкт, рядок або будь-яку іншу.
А ось while
варіант:
function bidirectionalIndexOf(a, b, c, d){
c=a.length; d=c-1;
while(c--){
if(b===a[c]) return c;
if(b===a[d-c]) return d-c;
}
return c
}
// Usage
bidirectionalIndexOf(array,'value');
Як це можливо?
Я думаю, що простий розрахунок для отримання відображеного індексу в масиві настільки простий, що це в два рази швидше, ніж робити фактичну цикл ітерації.
Ось складний приклад, який робить три перевірки за ітерацію, але це можливо лише при більш тривалому обчисленні, що викликає уповільнення коду.
http://jsperf.com/bidirectionalindexof/2