Мне трудно понять, как переместить элемент массива. Например, учитывая следующее:
var arr = [ 'a', 'b', 'c', 'd', 'e'];
Как я могу написать функцию, чтобы двигаться 'd'
раньше 'b'
?
Или 'a'
после 'c'
?
После перемещения индексы остальных элементов должны быть обновлены. Это означает, что в первом примере после хода arr [0] будет = 'a', arr [1] = 'd' arr [2] = 'b', arr [3] = 'c', arr [4] = «е»
Кажется, это должно быть довольно просто, но я не могу обернуть голову вокруг этого.
javascript
arrays
Марк Браун
источник
источник
const changeValuePosition = (arr, init, target) => {[arr[init],arr[target]] = [arr[target],arr[init]]; return arr}
init
иtarget
.Ответы:
Если вам нужна версия для npm, наиболее близким к этому ответу является array-move , хотя это не та реализация. Смотрите его использование раздел для более подробной информации. Предыдущая версия этого ответа (которая изменила Array.prototype.move) может быть найдена на npm в array.prototype.move .
У меня был довольно хороший успех с этой функцией:
Обратите внимание, что последнее
return
просто для целей тестирования:splice
выполняет операции с массивом на месте, поэтому возврат не требуется. По сути, этоmove
операция на месте. Если вы хотите избежать этого и вернуть копию, используйтеslice
.Пошаговое выполнение кода:
new_index
он больше длины массива, мы хотим (я полагаю) правильно заполнить массив новымиundefined
s. Этот маленький фрагмент обрабатывает это, нажимаяundefined
на массив, пока у нас не будет правильной длины.arr.splice(old_index, 1)[0]
мы склеиваем старый элемент.splice
возвращает элемент, который был вставлен, но он находится в массиве. В нашем примере выше это было[1]
. Итак, мы берем первый индекс этого массива, чтобы получить сырье1
там.splice
чтобы вставить этот элемент вместо new_index. Так как мы добавили массив выше, еслиnew_index > arr.length
, он, вероятно, появится в правильном месте, если они не сделали что-то странное, например, передать отрицательное число.Более привлекательная версия для учета отрицательных показателей:
Который должен учитывать такие вещи, как
array_move([1, 2, 3], -1, -2)
правильно (переместите последний элемент со второго на последнее место). Результат для этого должен быть[1, 3, 2]
.В любом случае, в исходном вопросе, вы могли бы сделать
array_move(arr, 0, 2)
дляa
AFTERc
. Ибоd
раньшеb
вы бы сделалиarray_move(arr, 3, 1)
.источник
.hasOwnProperty
проверку при выполнении итераций с такими вещами, как for..in, особенно с такими библиотеками, как Prototype и MooTools, которые модифицируют прототипы. Во всяком случае, я не чувствовал, что это было особенно важной проблемой в сравнительно ограниченном примере, подобном этому, и в сообществе есть хороший раскол по поводу того, является ли модификация прототипа хорошей идеей. Тем не менее, проблемы итераций, как правило, меньше всего волнуют.this[new_index] = undefined;
внутриif
блока. Поскольку массивы Javascript редки, это увеличит размер массива, добавив new_index для.splice
работы, но без необходимости создания каких-либо промежуточных элементов.this[new_index] = undefined
вы сделаете это, то поместитеundefined
в слот массива перед правильным индексом. (Например,[1,2,3].move(0,10)
будет1
в слоте 10 иundefined
в слоте 9.) Скорее, если разреженность в порядке, мы могли бы обойтисьthis[new_index] = this.splice(old_index, 1)[0]
без другого вызова соединения (вместо этого сделайте это if / else).Вот один лайнер, который я нашел на JSPerf ....
это здорово читать, но если вы хотите производительность (в небольших наборах данных), попробуйте ...
Я не могу взять кредит, все это должно пойти к Ричарду Скарротту . В этом тесте производительности он превосходит метод на основе сплайсинга для небольших наборов данных . Однако, как указывает Дарвейн, он значительно медленнее для больших наборов данных .
источник
from >= to ? this.splice(to, 0, this.splice(from, 1)[0]) : this.splice(to - 1, 0, this.splice(from, 1)[0]);
Мне нравится этот способ. Это сжато, и это работает.
Примечание: всегда не забывайте проверять границы вашего массива.
Запустите Snippet на jsFiddle
источник
поскольку функция является цепной, это тоже работает:
демо здесь
источник
Мой 2с. Легко читается, работает, работает быстро, не создает новых массивов.
источник
array
, как это было сделано в конце.Получил эту идею от @Reid, чтобы поместить что-то на место элемента, который должен быть перемещен, чтобы сохранить размер массива постоянным. Это упрощает расчеты. Кроме того, добавление пустого объекта обладает дополнительными преимуществами возможности уникального поиска в дальнейшем. Это работает, потому что два объекта не равны, пока они не ссылаются на один и тот же объект.
Итак, вот функция, которая принимает исходный массив и исходные целевые индексы. Вы можете добавить его в Array.prototype, если это необходимо.
источник
sourceIndex = 0
,destIndex = 1
destIndex
должен быть индексом перед перемещением исходного элемента в массиве.Это основано на решении @ Reid. Кроме:
Array
прототип.undefined
элементы, оно просто перемещает элемент в крайнее правое положение.Функция:
Модульные тесты:
источник
Вот мое однострочное решение ES6 с необязательным параметром
on
.Адаптация первого решения, предложенного
digiguru
Параметр
on
- это номер элемента, начиная с которогоfrom
вы хотите переместиться.источник
splice
МетодArray
может помочь: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/spliceПросто имейте в виду, что это может быть относительно дорого, поскольку он должен активно переиндексировать массив.
источник
Один из подходов заключается в создании нового массива с кусочками в нужном вам порядке, используя метод slice.
пример
источник
arr2
из-за операций конкатенации вы становитесь строкой, верно? :) Это в конечном итоге"adc,de"
.Вы можете реализовать базовое исчисление и создать универсальную функцию для перемещения элемента массива из одной позиции в другую.
Для JavaScript это выглядит так:
Проверьте "движущиеся элементы массива" в "gloommatter" для подробного объяснения.
http://www.gloommatter.com/DDesign/programming/moving-any-array-elements-universal-function.html
источник
Я реализовал неизменное
ECMAScript 6
решение, основанное на@Merc
ответе здесь:Имена переменных могут быть сокращены, просто используйте длинные, чтобы код мог объяснить сам себя.
источник
array
сразу жеfromIndex === toIndex
, а создать только,newArray
если это не так? Неизменность не означает, что для каждого вызова функции должна быть создана одна свежая копия, даже если нет изменений. Просто спросив b / c, мотив для увеличения длины этой функции (по сравнению с однострочными строками на основе сплайсинга) - это производительность, и онаfromIndex
может часто равняться вtoIndex
зависимости от использования.Мне был нужен неизменный метод перемещения (тот, который не изменял исходный массив), поэтому я адаптировал принятый ответ @ Reid, чтобы просто использовать Object.assign для создания копии массива перед выполнением сращивания.
Вот jsfiddle, показывающий это в действии .
источник
http://plnkr.co/edit/JaiAaO7FQcdPGPY6G337?p=preview
источник
В итоге я скомбинировал два из них, чтобы работать немного лучше при перемещении как на малые, так и на большие расстояния. Я получаю довольно последовательные результаты, но, возможно, кто-то умнее меня будет немного подправлять, чтобы работать по-разному для разных размеров и т. Д.
Использование некоторых других методов при перемещении объектов на небольшие расстояния было значительно быстрее (х10), чем при сращивании. Это может измениться в зависимости от длины массива, но это верно для больших массивов.
http://jsperf.com/arraymove-many-sizes
источник
Во многих местах сказано ( добавление пользовательских функций в Array.prototype ), игра с прототипом Array может быть плохой идеей, в любом случае, я объединил лучшее из различных постов, которые я получил, используя современный Javascript:
Надежда может быть полезна каждому
источник
Эта версия не идеальна для всех целей, и не всем нравятся выражения с запятыми, но вот строка с одним выражением, которая является чистым выражением и создает свежую копию:
Слегка улучшенная по производительности версия возвращает входной массив, если перемещение не требуется, все еще нормально для неизменного использования, так как массив не изменится, и это все еще чистое выражение:
Вызов любого из
то есть он основан на распространении для создания новой копии. Использование фиксированной арности 3
move
поставит под угрозу либо одно свойство выражения, либо неразрушающий характер, либо выигрыш в производительностиsplice
. Опять же, это скорее пример, который соответствует некоторым критериям, чем предложение для производственного использования.источник
Array.move.js
Резюме
Перемещает элементы в массиве, возвращая массив, содержащий перемещенные элементы.
Синтаксис
параметры
index : индекс для перемещения элементов. Если отрицательный, индекс начнется с конца.
howMany : количество элементов для перемещения из индекса .
toIndex : индекс массива, в который нужно поместить перемещенные элементы. Если отрицательный, toIndex начнется с конца.
Применение
Polyfill
источник
.move
похоже, что он должен работать (я не проверял его), вы должны заметить, что он не является частью какого-либо стандарта. Также полезно предупредить людей, что функции polyfill / monkeypatched могут сломать некоторый код, который предполагает, что все перечисляемое принадлежит им.Я использовал хороший ответ @Reid , но изо всех сил пытался переместить элемент из конца массива на один шаг дальше - в начало (как в цикле ). Например, ['a', 'b', 'c'] должны стать ['c', 'a', 'b'] путем вызова .move (2,3)
Я добился этого, изменив регистр для new_index> = this.length.
источник
В дополнение к превосходному ответу Рейда (и потому что я не могу комментировать); Вы можете использовать модуль по модулю, чтобы и отрицательные индексы и слишком большие индексы «переворачивались»:
источник
источник
Я думал, что это проблема обмена, но это не так. Вот мое однострочное решение:
Вот небольшой тест:
источник
результат:
источник
источник
источник
Неизменяемая версия без копии массива:
источник
Я думаю, что лучший способ - это определить новое свойство для массивов.
источник
Другой чистый вариант JS, использующий оператор распространения массива ES6 без мутации
источник
Этот метод сохранит исходный массив и проверит наличие ошибок ограничения.
источник