I have an array with 7 items in it. I want to move a few items to a different index in the same order as it was in the original array. I have pasted in code snippet on whatever I tried so far.
let originalArray = ['a','b','c','d','e','f','g']; let itemsToBeMoved = ['c','f','e']; let newIndexToBeMoved = 4; //expected result is ['a','b','d','c','e','f','g']; let movableItemsIndex = []; movableItemsIndex.push(originalArray.indexOf('c')); movableItemsIndex.push(originalArray.indexOf('f')); movableItemsIndex.push(originalArray.indexOf('e')); //To be Moved items has to be sorted as in originalArray movableItemsIndex.sort(); let itemsToBeMovedSorted = [originalArray[movableItemsIndex[0]],originalArray[movableItemsIndex[1]],originalArray[movableItemsIndex[2]]]; //Removing items before inserting to items to new position while(movableItemsIndex.length) { originalArray.splice(movableItemsIndex.pop(), 1); } let newUpdatedArray = [...originalArray],j=0; for(let i = newIndexToBeMoved;i < originalArray.length; i++){ newUpdatedArray[i] = itemsToBeMovedSorted[j]; j++; } console.log(newUpdatedArray);
Assuming that all elements are unique:
let originalArray = ['a','b','c','d','e','f','g']; let itemsToBeMoved = ['c','f','e']; let newIndexToBeMoved = 4; // find the value of the element the marks the insertion point let insertBefore = originalArray[newIndexToBeMoved]; // in original sequence order, check for presence in the removal // list, *and* remove them from the original array let moved = []; for (let i = 0; i < originalArray.length; ) { let value = originalArray[i]; if (itemsToBeMoved.indexOf(value) >= 0) { moved.push(value); originalArray.splice(i, 1); } else { ++i; } } // find the new index of the insertion point let insertionIndex = originalArray.indexOf(insertBefore); if (insertionIndex < 0) { insertionIndex = originalArray.length; } // and add the elements back in originalArray.splice(insertionIndex, 0, ...moved); console.log(originalArray);
This can be solved many ways, but here is a quick run-down of what could be done:
const move = (arr, items, index) => { const present = new Map(items.map(item => [item, arr.indexOf(item)])); const altered = arr.filter(item => !present.has(item)); altered.splice(arr.indexOf(arr[index - 1]), 0, ...([...present.entries()] .filter(([k, v]) => v !== -1) .sort(([, k1], [, k2]) => k1 - k2) .map(([k, v]) => k))); return altered; } const moved = move(['a','b','c','d','e','f','g'], ['c','f','e'], 4); console.log(moved);
.as-console-wrapper { top: 0; max-height: 100% !important; }
Here's a way to do it with typescript
and generics
. It does not mutate the array, it's very fast (used the conclusions of this article to make it).
When moving items to a new position, there is always a range of items affected by the move. By affected, I mean that within that range, all items will have to move. I calculate the min/max of the range, any items outside that range will simply be copied from the old to new array.
Then, depending whether the items are moved up or down in the array, I copy each items from old to new array taking into account the offset of the move.
export const arrayMove = <ItemType>({
arr,
from,
to,
movedItemsCount = 1,
}: {
arr: ItemType[]
from: number
to: number
movedItemsCount?: number
}) => {
if (from === to) return arr
const minAffected = Math.min(from, to)
const maxAffected = Math.max(to, from + movedItemsCount - 1)
const pushedItemsCount = maxAffected - minAffected + 1 - movedItemsCount
const newArr: ItemType[] = []
newArr.length = arr.length
for (let i = 0; i < arr.length; i++) {
if (i < minAffected || i > maxAffected) {
// When i is outside the affected range,
// items are identical in new and old arrays
newArr[i] = arr[i]
} else {
// Moving items down
if (to > from) {
if (i < to - movedItemsCount + 1) {
// Write pushed items
newArr[i] = arr[i + movedItemsCount]
} else {
// Write moved items
newArr[i] = arr[i - pushedItemsCount]
}
} else {
// Moving items up
if (i < to + movedItemsCount) {
// Write moved items
newArr[i] = arr[i + pushedItemsCount]
} else {
// Write pushed items
newArr[i] = arr[i - movedItemsCount]
}
}
}
}
return newArr
}
Try this:
const originalArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; const itemsToBeMoved = ['c', 'f', 'e']; const newIndexToBeMoved = 4; originalArray.splice(newIndexToBeMoved, 0, itemsToBeMoved) console.log(originalArray.flat())
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.