Move an array element from one array position to another

后端 未结 30 2473
渐次进展
渐次进展 2020-11-22 08:36

I\'m having a hard time figuring out how to move an array element. For example, given the following:

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


        
相关标签:
30条回答
  • 2020-11-22 08:51

    I thought this was a swap problem but it's not. Here's my one-liner solution:

    const move = (arr, from, to) => arr.map((item, i) => i === to ? arr[from] : (i >= Math.min(from, to) && i <= Math.max(from, to) ? arr[i + Math.sign(to - from)] : item));
    

    Here's a small test:

    let test = ['a', 'b', 'c', 'd', 'e'];
    console.log(move(test, 0, 2)); // [ 'b', 'c', 'a', 'd', 'e' ]
    console.log(move(test, 1, 3)); // [ 'a', 'c', 'd', 'b', 'e' ]
    console.log(move(test, 2, 4)); // [ 'a', 'b', 'd', 'e', 'c' ]
    console.log(move(test, 2, 0)); // [ 'c', 'a', 'b', 'd', 'e' ]
    console.log(move(test, 3, 1)); // [ 'a', 'd', 'b', 'c', 'e' ]
    console.log(move(test, 4, 2)); // [ 'a', 'b', 'e', 'c', 'd' ]
    console.log(move(test, 4, 0)); // [ 'e', 'a', 'b', 'c', 'd' ]
    
    0 讨论(0)
  • 2020-11-22 08:52

    If you'd like a version on npm, array-move is the closest to this answer, although it's not the same implementation. See its usage section for more details. The previous version of this answer (that modified Array.prototype.move) can be found on npm at array.prototype.move.


    I had fairly good success with this function:

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

    Note that the last return is simply for testing purposes: splice performs operations on the array in-place, so a return is not necessary. By extension, this move is an in-place operation. If you want to avoid that and return a copy, use slice.

    Stepping through the code:

    1. If new_index is greater than the length of the array, we want (I presume) to pad the array properly with new undefineds. This little snippet handles this by pushing undefined on the array until we have the proper length.
    2. Then, in arr.splice(old_index, 1)[0], we splice out the old element. splice returns the element that was spliced out, but it's in an array. In our above example, this was [1]. So we take the first index of that array to get the raw 1 there.
    3. Then we use splice to insert this element in the new_index's place. Since we padded the array above if new_index > arr.length, it will probably appear in the right place, unless they've done something strange like pass in a negative number.

    A fancier version to account for negative indices:

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

    Which should account for things like array_move([1, 2, 3], -1, -2) properly (move the last element to the second to last place). Result for that should be [1, 3, 2].

    Either way, in your original question, you would do array_move(arr, 0, 2) for a after c. For d before b, you would do array_move(arr, 3, 1).

    0 讨论(0)
  • 2020-11-22 08:53

    You can implement some basic Calculus and create a universal function for moving array element from one position to the other.

    For JavaScript it looks like this:

    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 "moving array elements" at "gloommatter" for detailed explanation.

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

    0 讨论(0)
  • 2020-11-22 08:53

    var ELEMS = ['a', 'b', 'c', 'd', 'e'];
    /*
        Source item will remove and it will be placed just after destination
    */
    function moveItemTo(sourceItem, destItem, elements) {
        var sourceIndex = elements.indexOf(sourceItem);
        var destIndex = elements.indexOf(destItem);
        if (sourceIndex >= -1 && destIndex > -1) {
            elements.splice(destIndex, 0, elements.splice(sourceIndex, 1)[0]);
        }
        return elements;
    }
    console.log('Init: ', ELEMS);
    var result = moveItemTo('a', 'c', ELEMS);
    console.log('BeforeAfter: ', result);

    0 讨论(0)
  • 2020-11-22 08:55

    I like this way. It's concise and it works.

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

    Note: always remember to check your array bounds.

    Run Snippet in jsFiddle

    0 讨论(0)
  • 2020-11-22 08:57

    Another pure JS variant using ES6 array spread operator with no mutation

    const reorder = (array, sourceIndex, destinationIndex) => {
    	const smallerIndex = Math.min(sourceIndex, destinationIndex);
    	const largerIndex = Math.max(sourceIndex, destinationIndex);
    
    	return [
    		...array.slice(0, smallerIndex),
    		...(sourceIndex < destinationIndex
    			? array.slice(smallerIndex + 1, largerIndex + 1)
    			: []),
    		array[sourceIndex],
    		...(sourceIndex > destinationIndex
    			? array.slice(smallerIndex, largerIndex)
    			: []),
    		...array.slice(largerIndex + 1),
    	];
    }
    
    // returns ['a', 'c', 'd', 'e', 'b', 'f']
    console.log(reorder(['a', 'b', 'c', 'd', 'e', 'f'], 1, 4))
          
     

    0 讨论(0)
提交回复
热议问题