【问题标题】:Reordering arrays重新排序数组
【发布时间】:2026-01-27 23:40:01
【问题描述】:

说,我有一个如下所示的数组:

var playlist = [
    {artist:"Herbie Hancock", title:"Thrust"},
    {artist:"Lalo Schifrin", title:"Shifting Gears"},
    {artist:"Faze-O", title:"Riding High"}
];

如何将元素移动到另一个位置?

例如,我想将{artist:"Lalo Schifrin", title:"Shifting Gears"} 移动到最后。

我尝试使用拼接,如下所示:

var tmp = playlist.splice(2,1);
playlist.splice(2,0,tmp);

但它不起作用。

【问题讨论】:

  • “不起作用”是什么意思——它是否会引发错误,是否没有任何改变,是否会以您不希望的方式改变您的数组?我觉得这很合理。

标签: javascript arrays sorting


【解决方案1】:

Array.splice 的语法是:

yourArray.splice(index, howmany, element1, /*.....,*/ elementX);

地点:

  • index 是数组中要开始从中删除元素的位置
  • howmany 是您要从 index 中删除的元素数量
  • element1, ..., elementX 是您要从 index 位置插入的元素。

这意味着splice() 可用于删除元素、添加元素或替换数组中的元素,具体取决于您传递的参数。

请注意,它返回一个已删除元素的数组。

一些好的和通用的东西是:

Array.prototype.move = function (from, to) {
  this.splice(to, 0, this.splice(from, 1)[0]);
};

然后只需使用:

var ar = [1,2,3,4,5];
ar.move(0,3);
alert(ar) // 2,3,4,1,5

图表:

【讨论】:

  • 这是一个很好的答案,并且 splice() 中的 splice() 可以很好地完成这项工作。然而,应该注意的是,向 Array 原型添加 move() 方法称为“Monkey Patching”,通常被认为是不好的做法。 *.com/questions/5741877/…
  • 使用 splice() 似乎很棘手,有一些难以解决的极端情况 - 即一次重新排序两个以上项目的情况。
【解决方案2】:

如果您知道索引,则可以使用如下简单函数轻松交换元素:

function swapElement(array, indexA, indexB) {
  var tmp = array[indexA];
  array[indexA] = array[indexB];
  array[indexB] = tmp;
}

swapElement(playlist, 1, 2);
// [{"artist":"Herbie Hancock","title":"Thrust"},
//  {"artist":"Faze-O","title":"Riding High"},
//  {"artist":"Lalo Schifrin","title":"Shifting Gears"}]

数组索引只是数组对象的属性,所以你可以交换它的值。

【讨论】:

  • 谢谢,@CMS。如果我交换均值不想替换订单...例如,如果我选择第 3 个对象到第 1 个位置,我想将 1 交换为 2,将 2 交换为 3 作为 1
【解决方案3】:

对于感兴趣的人来说,这里是一个不可变的版本:

function immutableMove(arr, from, to) {
  return arr.reduce((prev, current, idx, self) => {
    if (from === to) {
      prev.push(current);
    }
    if (idx === from) {
      return prev;
    }
    if (from < to) {
      prev.push(current);
    }
    if (idx === to) {
      prev.push(self[from]);
    }
    if (from > to) {
      prev.push(current);
    }
    return prev;
  }, []);
}

【讨论】:

  • 嗨,你能向我解释一下这个功能相对于上述答案的好处吗?
  • 这个解决方案不修改原始元素,而是返回一个新数组,其中的条目被移动。
  • @Xogno 在像 React 这样经常需要不可变对象来检测变化的框架中特别有用
  • 谢谢两位的解释
【解决方案4】:

使用 ES6,您可以执行以下操作:

const swapPositions = (array, a ,b) => {
  [array[a], array[b]] = [array[b], array[a]]
}

let array = [1,2,3,4,5];
swapPositions(array,0,1);

/// => [2, 1, 3, 4, 5]

【讨论】:

  • 这会交换两个元素的位置。问题是重新排序。
【解决方案5】:

如果您不知道当前记录在哪里,您可以随时使用排序方法:

playlist.sort(function (a, b) {
    return a.artist == "Lalo Schifrin" 
               ? 1    // Move it down the list
               : 0;   // Keep it the same
});

【讨论】:

  • return +(a.artist == "Lalo Schifrin")怎么样
  • @Funko 你可以这样做,如果你喜欢简洁而不是冗长。
【解决方案6】:

将2改为1作为移除元素时拼接调用中的第一个参数:

var tmp = playlist.splice(1, 1);
playlist.splice(2, 0, tmp[0]);

【讨论】:

  • 应该是 playlist.splice(2,0,tmp[0]);对吗?
【解决方案7】:

编辑:请查看Andy's answer,因为他的答案是第一位的,这只是他的延伸

我知道这是一个老问题,但我认为包含 Array.prototype.sort() 是值得的。

这是来自 MDN along with the link 的示例

var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
  return a - b;
});
console.log(numbers);

// [1, 2, 3, 4, 5]

幸运的是,它不仅适用于数字:

arr.sort([compareFunction])

compareFunction

指定定义排序顺序的函数。如果省略,则数组根据每个字符的 Unicode 码位值,根据每个元素的字符串转换进行排序。

我注意到您是按名字订购的:

let playlist = [
    {artist:"Herbie Hancock", title:"Thrust"},
    {artist:"Lalo Schifrin", title:"Shifting Gears"},
    {artist:"Faze-O", title:"Riding High"}
];

// sort by name
playlist.sort((a, b) => {
  if(a.artist < b.artist) { return -1; }
  if(a.artist > b.artist) { return  1; }

  // else names must be equal
  return 0;
});

请注意,如果您想按姓氏订购它们,则必须同时拥有 first_namelast_name 的密钥,或者做一些正则表达式魔术,我不能这样做 XD

希望有帮助:)

【讨论】:

  • 这应该是对this answer的编辑或评论。
  • @JaredSmith 哎呀!我没有看到他的回答。我没有足够的分数或任何东西来编辑他的问题,而且我认为不应该在评论中添加所有这些信息。因此,在有人编辑他的问题之前,我会简单地补充一下,这是对 Andy E 答案的扩展(就像我应该做的那样)。
  • 我觉得现在很好:)
【解决方案8】:

不可变版本,无副作用(不改变原始数组):

const testArr = [1, 2, 3, 4, 5];

function move(from, to, arr) {
    const newArr = [...arr];

    const item = newArr.splice(from, 1)[0];
    newArr.splice(to, 0, item);

    return newArr;
}

console.log(move(3, 1, testArr));

// [1, 4, 2, 3, 5]

codepen:https://codepen.io/mliq/pen/KKNyJZr

【讨论】:

    【解决方案9】:

    试试这个:

    playlist = playlist.concat(playlist.splice(1, 1));
    

    【讨论】:

      【解决方案10】:

      如果您只想将一个项目从任意位置移动到数组的末尾,这应该可以:

      function toEnd(list, position) {
          list.push(list.splice(position, 1));
          return list;
      }
      

      如果您想将多个项目从某个任意位置移动到末尾,您可以这样做:

      function toEnd(list, from, count) {
          list.push.apply(list, list.splice(from, count));
          return list;
      }
      

      如果您想将多个项目从某个任意位置移动到某个任意位置,请尝试:

      function move(list, from, count, to) {
          var args = [from > to ? to : to - count, 0];
          args.push.apply(args, list.splice(from, count));
          list.splice.apply(list, args);
      
          return list;
      }
      

      【讨论】:

        【解决方案11】:

        作为一个简单的可变解决方案,您可以连续调用 splice 两次:

        playlist.splice(playlist.length - 1, 1, ...playlist.splice(INDEX_TO_MOVE, 1))
        

        另一方面,一个简单的不可变解决方案可以使用 slice,因为此方法从原始数组返回一个部分的副本而不更改它:

        const copy = [...playlist.slice(0, INDEX_TO_MOVE - 1), ...playlist.slice(INDEX_TO_MOVE), ...playlist.slice(INDEX_TO_MOVE - 1, INDEX_TO_MOVE)]
        

        【讨论】:

          【解决方案12】:

          以这种方式重新排列其工作

           var tmpOrder = playlist[oldIndex];
              playlist.splice(oldIndex, 1);
              playlist.splice(newIndex, 0, tmpOrder);
          

          我希望这会奏效

          【讨论】:

          • 这对现有答案有什么好处?