javascript - 자르기 - 자바스크립트 배열 검색




한 배열 위치에서 다른 배열 위치로 배열 요소 이동 (14)

splice () 메서드는 배열에 항목을 추가 / 제거하고 제거 된 항목을 반환합니다.

참고 :이 방법은 원래 배열을 변경합니다. / 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"]

함수가 chainable 이기 때문에 이것 역시 작동합니다 :

alert(arr.move(0,2).join(','));

여기서 데모하기

배열 요소를 이동하는 방법을 알아내는 데 어려움을 겪고 있습니다. 예를 들어 다음과 같습니다.

var arr = [ 'a', 'b', 'c', 'd', 'e'];

'b' 앞에 'b' 'd' 를 이동하는 함수를 작성하려면 어떻게해야합니까?

또는 'a' 다음에 'c' ?

이동 후에는 나머지 요소의 색인을 업데이트해야합니다. 즉, arr [1] = 'd'arr [2] = 'b', arr [3] = 'c', arr [4] = ' '이자형'

이것은 꽤 간단해야하지만, 나는 그 주위에 내 머리를 감쌀 수 없어 보인다.


Array.move.js

개요

배열 내에서 요소를 이동하여 이동 된 요소가 들어있는 배열을 반환합니다.

통사론

array.move(index, howMany, toIndex);

매개 변수

index : 요소를 이동할 색인입니다. 음수 인 경우 색인 은 끝에서 시작합니다.

howMany : 인덱스 에서 이동할 요소의 수입니다.

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"]

폴리필

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;
    }
});

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 사용하십시오.

코드를 살펴 보자.

  1. new_index 가 배열의 길이보다 길면 우리는 새로운 undefined 배열을 적절하게 new_index 를 원합니다. 이 작은 스 니펫은 적절한 길이가 될 때까지 배열에서 undefined 를 밀어서 처리합니다.
  2. 그런 다음 arr.splice(old_index, 1)[0] 에서 이전 요소를 분리합니다. splicesplice 된 요소를 반환하지만 배열에 있습니다. 우리의 위의 예에서 이것은 [1] 이었다. 그래서 우리는 그 배열의 첫 번째 인덱스를 가져 와서 원시 1 을 얻습니다.
  3. 그런 다음 splice 를 사용하여이 요소를 new_index의 위치에 삽입합니다. new_index > arr.length 인 경우 위의 배열을 패딩 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) 를 수행 할 것이다. d 앞에 barray_move(arr, 3, 1) 합니다.


기본 Calculus를 구현하고 배열 요소를 한 위치에서 다른 위치로 이동시키는 범용 함수를 만들 수 있습니다.

자바 스크립트의 경우 다음과 같이 보입니다.

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; 

}

자세한 설명은 "gloomatter"에서 "배열 요소 이동"을 확인하십시오.

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


나는 이런 식으로 좋아한다. 그것은 작동합니다, 그것은 빠르고 우아합니다.

function arraymove(arr, fromIndex, toIndex) {
    var element = arr[fromIndex];
    arr.splice(fromIndex, 1);
    arr.splice(toIndex, 0, element);
}

참고 : 배열 경계를 항상 확인하십시오.


나는 작은 거리와 큰 거리를 모두 움직일 때 좀 더 잘 작동하도록이 두 가지를 결합하는 것을 끝내었다. 나는 꽤 일관된 결과를 얻지 만, 이것은 나보다 똑똑한 누군가가 다른 크기 등을 다르게 다르게하기 위해 약간 조정될 수 있습니다.

객체를 작은 거리로 이동할 때 다른 방법을 사용하면 splice를 사용하는 것보다 훨씬 더 빨랐습니다 (x10). 배열 길이에 따라 달라질 수 있지만 대용량 배열의 경우에도 마찬가지입니다.

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


배열의 크기를 일정하게 유지하기 위해 이동해야하는 항목 대신에 @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가 수락 한 대답을 적용하여 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 입니다.


옵션 매개 변수가 설정된라이너 ES6 솔루션 이 있습니다.

if (typeof Array.prototype.move === "undefined") {
  Array.prototype.move = function(from, to, on = 1) {
    this.splice(to, 0, ...this.splice(from, on))
  }
}

digiguru 제안한 첫 번째 솔루션의 적응

on 은 이동할 요소의 시작 번호입니다.


이 버전은 모든 용도에 이상적이 아니며 모든 사용자가 쉼표 표현을 좋아하는 것은 아니지만 여기에 새로운 표현을 작성하는 한 줄짜리 표현이 있습니다.

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

성능이 약간 개선 된 버전은 이동이 필요하지 않으면 입력 배열을 반환하지만, 배열은 변경되지 않고 여전히 순수한 표현이므로 불변 사용에는 여전히 유효합니다.

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

어느 쪽인가의 호출은

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

즉, 새로운 사본을 생성하기 위해 확산에 의존합니다. 고정 된 동작을 사용하면 단일 표현 속성 또는 비파괴적인 특성 또는 splice 의 성능 이점을 위태롭게 할 수 있습니다. 다시 말하면 프로덕션 용도에 대한 제안보다 몇 가지 기준을 충족시키는 예제가 더 많습니다.


한 가지 방법은 slice 메서드를 사용하여 원하는 순서대로 조각을 사용하여 새 배열을 만드는 것입니다.

var arr = [ 'a', 'b', 'c', 'd', 'e'];
var arr2 = arr.slice(0,1).concat( ['d'] ).concat( arr.slice(2,4) ).concat( arr.slice(4) );
  • arr.slice (0,1)는 당신에게 [ 'a']를줍니다.
  • arr.slice (2,4)는 당신에게 [ 'b', 'c']를줍니다.
  • arr.slice (4)는 당신에게 [ 'e']를줍니다.

Reid의 훌륭한 대답에 덧붙여 (그리고 내가 말할 수 없기 때문에); 모듈러스를 사용하여 제외 인덱스와 너무 큰 인덱스를 모두 "롤 오버"할 수 있습니다.

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)); 


@Reid에 대한 멋진 답변을 사용했지만 배열의 끝에서부터 한 단계 더 나아가서 처음부터 ( 루프 처럼) 움직이는 데 어려움을 겪었습니다. 예를 들어 .move (2,3)를 호출하여 [ 'a', 'b', 'c'] [c, a, b]

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
    };

    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





arrays