重新排列数组


98

说,我有一个看起来像这样的数组:

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

但这是行不通的。


3
“不起作用”是什么意思-它会引发错误,什么都不会改变,是否会以您不希望的方式改变数组?在我看来,这很合理。
雅各布·马蒂森

Answers:


220

的语法Array.splice为:

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

哪里:

  • index是您要开始从中删除元素的数组中的位置
  • 的howmany是你想要多少元素从删除索引
  • element1,...,elementX是要从位置索引插入的元素。

这意味着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

图解:

算法图


17
这是一个很好的答案,并且splice()中的splice()做得很好。但是,应注意,将mov()方法添加到Array原型称为“猴子修补”,通常被认为是不好的做法。 stackoverflow.com/questions/5741877/…–
亚伦·西卡利

20

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

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交换为2,将2交换为3为1
Peri

13

这是对感兴趣的人的不变版本:

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

1
此解决方案不修改原始元素,而是返回一个新数组,其中包含要移动的条目。
chmanie

7

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

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

1
它应该是playlist.splice(2,0,tmp [0]); 对?
Crisboot

7

使用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]

1
这将交换两个元素的位置。问题是要重新订购。
BY

5

如果您不知道当前记录在哪里,可以始终使用sort方法:

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")
Funkodebat 2015年

2
如果您喜欢简洁而不是冗长,则@Funko可以这样做。
安迪E

2

编辑:请先查看安迪的答案,因为他的答案排在第一位,这仅仅是他的扩展

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

这是来自MDN的示例以及链接

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

希望有帮助:)


这应该是对该答案的编辑或评论。
贾里德·史密斯

@JaredSmith糟糕!我没看到他的回答。我没有足够的观点或任何东西可以编辑他的问题,我不认为所有这些信息都应添加在评论中。因此,除非有人编辑他的问题,否则我将简单地补充一点,这是对Andy E答案的扩展(就像我应该做的那样)。
Jaacko Torus

我认为现在很好:)
Jared Smith,


1

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

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

0

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

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

-2

这样重新排列工作

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

我希望这会起作用


1
这与现有答案相加了什么?
贾里德·史密斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.