Маленькие причуды массивов
January 4, 2008 by Scratch
Иногда самые простые вещи могут поставить в тупик. Например, такая банальная штука как удаление элемента из массива. Собственно, с одним таким багом я столкнулся сегодня, и хотел бы его описать.
Итак, представим ситуацию. У нас есть JS код, в котором объявлен массив. Например, вида
var arr = [1,2,3,4,5,6,7];
Теперь перед нами стоит задача — удалить все четные элементы. Причем — удалить из исходного массива, а не получить новый
Для этого обычно пишется такая функция:
function cleanEven(arr) { // проходим по всем элементам for (var i = 0; i < arr.length; i++) { // Если элемент делится нацело на два if ( ! (arr[i] % 2)) { // Заменяем часть массива // с позиции i, длиной 1 на пустоту // (то есть удаляем i-тый элемент массива) arr.splice(i, 1); } } }
После запуска и выполнения все вроде бы работает. В моем тестовом запуске все сработало нормально.
Но — попробуем этот же код на массиве
var arr = [1,2,3,4,4,3,2,1];
После выполнения функции над этим массивом мы обнаружим, что внутри массива осталась четверка.
В чем проблема?
Дело в том, что при удалении элемента все остальные элементы перемещаются.
То есть — если из массива [1,2,3,4] удалить элемент ‘2′, то останется массив [1,3,4]. Соответственно, индексы элементов сменятся, и, при проходе по массиву при помощи цикла, мы (после удаления элемента) просто пропускаем элемент, следующий сразу за ним.
Так, в случае двух четных чисел мы удаляем первое из них, и пропускаем второе.
Решение очень простое и элегантное –
function cleanEven(arr) { // проходим по всем элементам НАЧИНАЯ С ПОСЛЕДНЕГО for (var i = arr.length-1; i >= 0 ; i--) { // Если элемент делится нацело на два if ( ! (arr[i] % 2)) { // Заменяем часть массива // с позиции i, длиной 1 на пустоту // (то есть удаляем i-тый элемент массива) arr.splice(i, 1); } } }
Filed under: Tips and tricks |