【问题标题】:How can I move multiple items in an array to different index in an Array?如何将数组中的多个项目移动到数组中的不同索引?
【发布时间】:2020-10-14 12:40:56
【问题描述】:

我有一个包含 7 个项目的数组。我想以与原始数组中相同的顺序将一些项目移动到不同的索引。到目前为止,我已将代码 sn-p 粘贴到我尝试过的任何内容上。

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

【问题讨论】:

  • splice 他们出去,splice 他们又回来了 - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • 什么定义了插入索引,假设 before 该索引的某些元素将被删除(从而更改其索引)?在搜索东西的上下文中,给出要重新插入移动元素的元素的 value 是否更有意义?
  • 问题是,因为我必须拼接必须移动的项目。原始 Array 中项目的索引发生更改。现在我必须一个接一个地插入项目的索引在拼接后无效。您可以在提供的 sn -p i 中看到预期的结果。

标签: javascript html jquery arrays


【解决方案1】:

假设所有元素都是唯一的:

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

【讨论】:

  • 对不起,我在接受之前测试了所有场景。我对此感到抱歉。如果我更改 itemsToBeMoved = ['f','e'] & newIndexToBeMoved = 6;那么输出是["e", "f", "a", "b", "c", "d", "g"],应该是["a", "b", "c", “d”、“g”、“e”、“f”、]
  • @SsNewbie 你有一个(缺乏)规范问题,因为在第一个例子中,你想要插入元素的 d 是索引为 3 的元素(零索引),而不是第四,即您在元素 3 和 4 之间插入。g 是第六个元素。如果您指定newIndexToBeMoved = 7(即在g 的位置之后的一个),我的代码会产生所需的输出。
  • 注:代码已更新以允许数组两端的边缘条件。
  • @Alnatik : 是的.. 所以如果 (newIndexToBeMoved = 6) (最后一个索引),那么必须让它 6 + 1,让它工作。另外,我尝试使用您之前的代码(在之前的更新之前)(originalArray.splice(newIndexToBeMoved === (originalArrayClone.length -1) ? (originalArray.length) : insertionIndex, 0, ...moved);),使用 originalArrayClone 是在拼接之前克隆 originalArray。
  • AFAICS 我当前的代码工作正常,但您无法通过指定 4(每个问题)和 6 每个评论来获得预期的结果 - 后者 必须为 7 以使其与 4 一致。
【解决方案2】:

这可以通过多种方式解决,但这里简要介绍一下可以采取的措施:

  1. 首先,您可以为要移动的项目创建一个“当前”映射(基于源数组中的位置)
  2. 现在,过滤数组,删除项目,但跟踪它们是否存在
  3. 将(排序的)存在的、过滤掉的值拼接到更改后的数组中的所需位置(基于源数组中的索引)

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

【讨论】:

  • 这不会产生 OP 所需的输出序列。
  • @Alnitak 我必须对值进行排序并从索引中减去 1,因为看起来它们的索引从 1 而不是 0 开始。感谢您的反馈。
  • 我相信索引从0开始,但它反映了插入点在原始序列中,因此最终的插入点将取决于删除元素的数量来自前面的元素。
  • 顺便说一句,你到底在排序什么?价值观,还是他们的立场?没有 cmets 很难说,但如果你对值进行排序,则 OP 没有这样的要求。要求是删除的元素以与原始数组中相同的顺序出现,而原始数组只是碰巧被排序。
  • @Alnitak 是因为我用了一张地图,但是我没有保留原来的索引序列,所以我想你的回复可以解决这个问题...我设置了现在的地图来存储原始的职位。这样我就可以过滤掉不存在的项目,然后再重新排序。
【解决方案3】:

这是一种使用typescriptgenerics 的方法。它不会改变数组,它非常快(使用this article的结论来制作)。

将项目移动到新位置时,总会有一系列项目受到移动的影响。受影响,我的意思是在那个范围内,所有项目都必须移动。我计算范围的最小值/最大值,超出该范围的任何项目都将简单地从旧数组复制到新数组。

然后,根据数组中的项目是向上还是向下移动,我将每个项目从旧数组复制到新数组,同时考虑到移动的偏移量。

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
}

【讨论】:

    【解决方案4】:

    试试这个:

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

    【讨论】:

    • 要移动的元素不是一个连续的组。它们需要单独移除,但可以整体重新插入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-30
    • 1970-01-01
    • 2022-01-22
    • 2020-05-02
    相关资源
    最近更新 更多