Переместить элемент массива из одной позиции массива в другую - PullRequest
426 голосов
/ 15 марта 2011

Мне трудно понять, как переместить элемент массива.Например, с учетом следующего:

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] ='e'

Кажется, это должно быть довольно просто, но я не могу обернуться вокруг него.

Ответы [ 21 ]

6 голосов
/ 05 июля 2012

Вы можете реализовать базовое исчисление и создать универсальную функцию для перемещения элемента массива из одной позиции в другую.

Для JavaScript это выглядит так:

function magicFunction (targetArray, indexFrom, indexTo) { 

    targetElement = targetArray[indexFrom]; 
    magicIncrement = (indexTo - indexFrom) / Math.abs (indexTo - indexFrom); 

    for (Element = indexFrom; Element != indexTo; Element += magicIncrement){ 
        targetArray[Element] = targetArray[Element + magicIncrement]; 
    } 

    targetArray[indexTo] = targetElement; 

}

Check out "перемещение элементов массива "в" gloommatter "для подробного объяснения.

http://www.gloommatter.com/DDesign/programming/moving-any-array-elements-universal-function.html

5 голосов
/ 26 июля 2016

Мне был нужен метод неизменного перемещения (тот, который не изменял исходный массив), поэтому я адаптировал принятый ответ @ Reid, чтобы просто использовать Object.assign для создания копии массива перед выполнением сращивания.

Array.prototype.immutableMove = function (old_index, new_index) {
  var copy = Object.assign([], this);
  if (new_index >= copy.length) {
      var k = new_index - copy.length;
      while ((k--) + 1) {
          copy.push(undefined);
      }
  }
  copy.splice(new_index, 0, copy.splice(old_index, 1)[0]);
  return copy;
};

Вот jsfiddle, показывающий его в действии .

4 голосов
/ 30 апреля 2014
    Array.prototype.moveUp = function (value, by) {
        var index = this.indexOf(value),
            newPos = index - (by || 1);

        if (index === -1)
            throw new Error("Element not found in array");

        if (newPos < 0)
            newPos = 0;

        this.splice(index, 1);
        this.splice(newPos, 0, value);
    };

    Array.prototype.moveDown = function (value, by) {
        var index = this.indexOf(value),
            newPos = index + (by || 1);

        if (index === -1)
            throw new Error("Element not found in array");

        if (newPos >= this.length)
            newPos = this.length;

        this.splice(index, 1);
        this.splice(newPos, 0, value);
    };



    var arr = ['banana', 'curyWurst', 'pc', 'remembaHaruMembaru'];

    alert('withiout changes= '+arr[0]+' ||| '+arr[1]+' ||| '+arr[2]+' ||| '+arr[3]);
    arr.moveDown(arr[2]);


    alert('third word moved down= '+arr[0] + ' ||| ' + arr[1] + ' ||| ' + arr[2] + ' ||| ' + arr[3]);
    arr.moveUp(arr[2]);
    alert('third word moved up= '+arr[0] + ' ||| ' + arr[1] + ' ||| ' + arr[2] + ' ||| ' + arr[3]);

http://plnkr.co/edit/JaiAaO7FQcdPGPY6G337?p=preview

3 голосов
/ 17 января 2018

Я реализовал неизменное решение ECMAScript 6, основанное на ответе @Merc здесь:

const moveItemInArrayFromIndexToIndex = (array, fromIndex, toIndex) => {
  if (fromIndex === toIndex) return array;

  const newArray = [...array];

  const target = newArray[fromIndex];
  const inc = toIndex < fromIndex ? -1 : 1;

  for (let i = fromIndex; i !== toIndex; i += inc) {
    newArray[i] = newArray[i + inc];
  }

  newArray[toIndex] = target;

  return newArray;
};

Имена переменных могут быть сокращены, просто используются длинные, чтобы код могобъясни.

2 голосов
/ 02 ноября 2018

Эта версия не идеальна для всех целей, и не всем нравятся выражения с запятыми, но вот однострочный, чистый текст, создающий свежую копию:

const move = (from, to, ...a) => (a.splice(to, 0, ...a.splice(from, 1)), a)

Немного улучшена производительностьversion возвращает входной массив, если перемещение не требуется, все еще нормально для неизменного использования, так как массив не изменится, и это все еще чистое выражение:

const move = (from, to, ...a) => 
    from === to 
    ? a 
    : (a.splice(to, 0, ...a.splice(from, 1)), a)

Вызов любого из них:

const shuffled = move(fromIndex, toIndex, ...list)

то есть он основан на распространении для создания новой копии.Использование фиксированной арности 3 move поставит под угрозу либо свойство отдельного выражения, либо неразрушающий характер, либо выигрыш в производительности splice.Опять же, это скорее пример, который соответствует некоторым критериям, чем предложение для производственного использования.

2 голосов
/ 18 сентября 2012

Array.move.js

Сводка

Перемещает элементы в массиве, возвращая массив, содержащий перемещенные элементы.

Синтаксис

array.move(index, howMany, toIndex);

Параметры

index : индекс для перемещения элементов.Если отрицательное значение, index начнется с конца.

howMany : Количество элементов для перемещения из index .

toIndex : Индекс массива для размещения перемещенных элементов.Если отрицательный, toIndex начнется с конца.

Использование

array = ["a", "b", "c", "d", "e", "f", "g"];

array.move(3, 2, 1); // returns ["d","e"]

array; // returns ["a", "d", "e", "b", "c", "f", "g"]

Polyfill

Array.prototype.move || Object.defineProperty(Array.prototype, "move", {
    value: function (index, howMany, toIndex) {
        var
        array = this,
        index = parseInt(index) || 0,
        index = index < 0 ? array.length + index : index,
        toIndex = parseInt(toIndex) || 0,
        toIndex = toIndex < 0 ? array.length + toIndex : toIndex,
        toIndex = toIndex <= index ? toIndex : toIndex <= index + howMany ? index : toIndex - howMany,
        moved;

        array.splice.apply(array, [toIndex, 0].concat(moved = array.splice(index, howMany)));

        return moved;
    }
});
2 голосов
/ 26 июля 2013

В итоге я скомбинировал два из них, чтобы работать немного лучше при перемещении как на малые, так и на большие расстояния.Я получаю довольно непротиворечивые результаты, но, возможно, кто-то умнее, чем я, мог бы немного изменить их для работы с разными размерами и т. Д.х10), чем с помощью сплайсинга.Это может измениться в зависимости от длины массива, но это верно для больших массивов.

function ArrayMove(array, from, to) {
    if ( Math.abs(from - to) > 60) {
        array.splice(to, 0, array.splice(from, 1)[0]);
    } else {
        // works better when we are not moving things very far
        var target = array[from];
        var inc = (to - from) / Math.abs(to - from);
        var current = from;
        for (; current != to; current += inc) {
            array[current] = array[current + inc];
        }
        array[to] = target;    
    }
}

http://jsperf.com/arraymove-many-sizes

1 голос
/ 20 мая 2018

Как дополнение к Отличный ответ Рейда (и потому что я не могу комментировать); Вы можете использовать модуль по модулю, чтобы и отрицательные индексы и слишком большие индексы «переворачивались»:

function array_move(arr, old_index, new_index) {
  new_index =((new_index % arr.length) + arr.length) % arr.length;
  arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
  return arr; // for testing
}

// returns [2, 1, 3]
console.log(array_move([1, 2, 3], 0, 1)); 
1 голос
/ 14 февраля 2018

Во многих местах сказано ( добавление пользовательских функций в Array.prototype ). Игра с прототипом Array может быть плохой идеей. В любом случае, я объединил лучшее из различных постов, которые я использовал, современный Javascript:

    Object.defineProperty(Array.prototype, 'immutableMove', {
        enumerable: false,
        value: function (old_index, new_index) {
            var copy = Object.assign([], this)
            if (new_index >= copy.length) {
                var k = new_index - copy.length;
                while ((k--) + 1) { copy.push(undefined); }
            }
            copy.splice(new_index, 0, copy.splice(old_index, 1)[0]);
            return copy
        }
    });

    //how to use it
    myArray=[0, 1, 2, 3, 4];
    myArray=myArray.immutableMove(2, 4);
    console.log(myArray);
    //result: 0, 1, 3, 4, 2

Надежда может быть полезна каждому

1 голос
/ 02 февраля 2015

Я использовал хороший ответ @ Reid , но изо всех сил пытался переместить элемент из конца массива на один шаг дальше - в начало (как в цикле ). Например. ['a', 'b', 'c'] должны стать ['c', 'a', 'b'] путем вызова .move (2,3)

Я добился этого, изменив регистр для new_index> = this.length.

Array.prototype.move = function (old_index, new_index) {
        console.log(old_index + " " + new_index);
        while (old_index < 0) {
            old_index += this.length;
        }
        while (new_index < 0) {
            new_index += this.length;
        }
        if (new_index >= this.length) {
            new_index = new_index % this.length;
        }
        this.splice(new_index, 0, this.splice(old_index, 1)[0]);
        return this; // for testing purposes
    };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...