배열 요소를 이동하는 방법을 알아내는 데 어려움을 겪고 있습니다. 예를 들면 다음과 같습니다.
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] = ‘이자형’
이것은 매우 간단해야하지만 머리를 감쌀 수는 없습니다.
답변
npm의 버전을 원한다면 array-move 가이 답변에 가장 가깝지만 동일한 구현은 아닙니다. 자세한 내용은 사용법 섹션을 참조하십시오. 이 답변의 이전 버전 (Array.prototype.move 수정)은 npm에서 찾을 수 있습니다. array.prototype.move .
이 기능으로 상당히 성공했습니다.
function array_move(arr, old_index, new_index) {
if (new_index >= arr.length) {
var k = new_index - arr.length + 1;
while (k--) {
arr.push(undefined);
}
}
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));
마지막 return
은 테스트 목적으로 만 사용됩니다. splice
어레이에서 적절한 작업을 수행하므로 반환 할 필요가 없습니다. 확장하면이 작업 move
은 적절한 작업입니다. 이를 피하고 사본을 반환하려면을 사용하십시오 slice
.
코드 단계별 설명 :
- 경우
new_index
새와 배열이 제대로 패드에 배열, 우리는 (나는 가정) 원하는 길이보다 큰 경우undefined
의. 이 작은 스 니펫undefined
은 적절한 길이가 될 때까지 배열 을 밀어서이를 처리합니다 . - 그런 다음
arr.splice(old_index, 1)[0]
에서 이전 요소를 연결합니다.splice
접합 된 요소를 반환하지만 배열에 있습니다. 위의 예에서 이것은이었습니다[1]
. 따라서 해당 배열의 첫 번째 인덱스를 가져 와서1
. - 그런 다음
splice
이 요소를 new_index의 위치에 삽입합니다. 위의 배열을 위의 패딩했기 때문에new_index > arr.length
음수로 전달하는 것과 같은 이상한 일을하지 않는 한 올바른 위치에 나타납니다.
음수 지수를 설명하는 더 멋진 버전 :
function array_move(arr, old_index, new_index) {
while (old_index < 0) {
old_index += arr.length;
}
while (new_index < 0) {
new_index += arr.length;
}
if (new_index >= arr.length) {
var k = new_index - arr.length + 1;
while (k--) {
arr.push(undefined);
}
}
arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
return arr; // for testing purposes
};
// returns [1, 3, 2]
console.log(array_move([1, 2, 3], -1, -2));
어느 것이 array_move([1, 2, 3], -1, -2)
올바르게 설명해야합니까 (마지막 요소를 두 번째 위치에서 마지막 위치로 이동). 그 결과는[1, 3, 2]
.
어느 쪽이든, 원래의 질문에, 당신은 할 것이다 array_move(arr, 0, 2)
위한 a
후 c
. 들어 d
전에 b
, 당신이 할 것입니다 array_move(arr, 3, 1)
.
답변
JSPerf에서 찾은 라이너 하나입니다 …
Array.prototype.move = function(from, to) {
this.splice(to, 0, this.splice(from, 1)[0]);
};
읽는 것이 좋지만 (작은 데이터 세트에서) 성능을 원한다면 시도하십시오 …
Array.prototype.move2 = function(pos1, pos2) {
// local variables
var i, tmp;
// cast input parameters to integers
pos1 = parseInt(pos1, 10);
pos2 = parseInt(pos2, 10);
// if positions are different and inside array
if (pos1 !== pos2 && 0 <= pos1 && pos1 <= this.length && 0 <= pos2 && pos2 <= this.length) {
// save element from position 1
tmp = this[pos1];
// move element down and shift other elements up
if (pos1 < pos2) {
for (i = pos1; i < pos2; i++) {
this[i] = this[i + 1];
}
}
// move element up and shift other elements down
else {
for (i = pos1; i > pos2; i--) {
this[i] = this[i - 1];
}
}
// put element from position 1 to destination
this[pos2] = tmp;
}
}
크레딧을받을 수 없습니다 . 모두 Richard Scarrott 로 가야합니다 . 이 성능 테스트 에서 더 작은 데이터 세트에 대한 스플 라이스 기반 방법을 능가합니다 . 그러나 Darwayne이 지적한 것처럼 더 큰 데이터 세트 에서는 속도가 상당히 느립니다 .
답변
나는이 방법을 좋아한다. 간결하고 작동합니다.
function arraymove(arr, fromIndex, toIndex) {
var element = arr[fromIndex];
arr.splice(fromIndex, 1);
arr.splice(toIndex, 0, element);
}
참고 : 항상 배열 범위를 확인하십시오.
답변
접합부 () 메소드는 추가 / 배열로부터 /로 항목 및 복귀 제거 제거를 항목 (들).
참고 :이 방법은 원래 배열을 변경합니다. / w3schools /
Array.prototype.move = function(from,to){
this.splice(to,0,this.splice(from,1)[0]);
return this;
};
var arr = [ 'a', 'b', 'c', 'd', 'e'];
arr.move(3,1);//["a", "d", "b", "c", "e"]
var arr = [ 'a', 'b', 'c', 'd', 'e'];
arr.move(0,2);//["b", "c", "a", "d", "e"]
함수가 체인 가능 하므로 다음과 같이 작동합니다.
alert(arr.move(0,2).join(','));
답변
내 2c. 읽기 쉽고 작동하며 빠르며 새 배열을 만들지 않습니다.
function move(array, from, to) {
if( to === from ) return array;
var target = array[from];
var increment = to < from ? -1 : 1;
for(var k = from; k != to; k += increment){
array[k] = array[k + increment];
}
array[to] = target;
return array;
}
답변
배열 크기를 일정하게 유지하기 위해 이동 해야하는 항목 대신 무언가를 밀어 넣는 @Reid의 아이디어를 얻었습니다. 그것은 계산을 단순화합니다. 또한 빈 개체를 밀어 넣으면 나중에 고유하게 검색 할 수 있다는 이점이 있습니다. 두 객체가 동일한 객체를 참조 할 때까지 동일하지 않기 때문에 작동합니다.
({}) == ({}); // false
여기 소스 배열과 소스, 대상 인덱스를 취하는 함수가 있습니다. 필요한 경우 Array.prototype에 추가 할 수 있습니다.
function moveObjectAtIndex(array, sourceIndex, destIndex) {
var placeholder = {};
// remove the object from its initial position and
// plant the placeholder object in its place to
// keep the array length constant
var objectToMove = array.splice(sourceIndex, 1, placeholder)[0];
// place the object in the desired position
array.splice(destIndex, 0, objectToMove);
// take out the temporary object
array.splice(array.indexOf(placeholder), 1);
}
답변
이것은 @Reid의 솔루션을 기반으로합니다. 외:
- 나는 변경하지 않습니다
Array
프로토 타입을 . - 경계
undefined
에서 항목을 오른쪽으로 이동하면 항목이 생성되지 않고 항목이 가장 오른쪽 위치로 이동합니다.
함수:
function move(array, oldIndex, newIndex) {
if (newIndex >= array.length) {
newIndex = array.length - 1;
}
array.splice(newIndex, 0, array.splice(oldIndex, 1)[0]);
return array;
}
단위 테스트 :
describe('ArrayHelper', function () {
it('Move right', function () {
let array = [1, 2, 3];
arrayHelper.move(array, 0, 1);
assert.equal(array[0], 2);
assert.equal(array[1], 1);
assert.equal(array[2], 3);
})
it('Move left', function () {
let array = [1, 2, 3];
arrayHelper.move(array, 1, 0);
assert.equal(array[0], 2);
assert.equal(array[1], 1);
assert.equal(array[2], 3);
});
it('Move out of bounds to the left', function () {
let array = [1, 2, 3];
arrayHelper.move(array, 1, -2);
assert.equal(array[0], 2);
assert.equal(array[1], 1);
assert.equal(array[2], 3);
});
it('Move out of bounds to the right', function () {
let array = [1, 2, 3];
arrayHelper.move(array, 1, 4);
assert.equal(array[0], 1);
assert.equal(array[1], 3);
assert.equal(array[2], 2);
});
});