Sắp xếp lại các mảng


98

Giả sử, tôi có một mảng trông như thế này:

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

Làm cách nào để di chuyển một phần tử sang vị trí khác?

Tôi muốn di chuyển ví dụ, {artist:"Lalo Schifrin", title:"Shifting Gears"}đến cuối cùng.

Tôi đã thử sử dụng mối nối, như thế này:

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

Nhưng nó không hoạt động.


3
"Không hoạt động" có nghĩa là gì - nó có báo lỗi không, nó có thay đổi gì không, nó có thay đổi mảng của bạn theo cách bạn không có ý định không? Nó có vẻ hợp lý với tôi.
Jacob Mattison

Câu trả lời:


220

Cú pháp của Array.splicelà:

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

Ở đâu:

  • chỉ mục là vị trí trong mảng bạn muốn bắt đầu xóa các phần tử khỏi
  • howmany là bao nhiêu phần tử bạn muốn xóa khỏi chỉ mục
  • element1, ..., elementX là các phần tử bạn muốn chèn từ chỉ mục vị trí .

Điều này có nghĩa là splice()có thể được sử dụng để loại bỏ các phần tử, thêm phần tử hoặc thay thế các phần tử trong một mảng, tùy thuộc vào các đối số bạn truyền vào.

Lưu ý rằng nó trả về một mảng các phần tử bị loại bỏ.

Một cái gì đó tốt đẹp và chung chung sẽ là:

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

Sau đó, chỉ cần sử dụng:

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

Biểu đồ:

Sơ đồ thuật toán


17
Đây là một câu trả lời hay và splice () trong splice () hoạt động tốt. Tuy nhiên, cần lưu ý rằng việc thêm một phương thức move () vào nguyên mẫu Array được gọi là "Monkey Patch" và thường được coi là hành động xấu. stackoverflow.com/questions/5741877/…
Aaron Cicali,

20

Nếu bạn biết các chỉ mục, bạn có thể dễ dàng hoán đổi các phần tử, với một hàm đơn giản như sau:

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"}]

Chỉ mục mảng chỉ là thuộc tính của đối tượng mảng, vì vậy bạn có thể hoán đổi các giá trị của nó.


Cảm ơn, @CMS. Nếu tôi hoán đổi nghĩa là không muốn thay thế thứ tự ... Ví dụ, Nếu tôi chọn đối tượng thứ 3 thành vị trí thứ nhất, tôi muốn hoán đổi 1 thành 2 và 2 thành 3 thành 1
Peri

13

Đây là một phiên bản bất biến dành cho những ai quan tâm:

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;
  }, []);
}

Xin chào, bạn có thể giải thích cho tôi những lợi ích của chức năng này qua câu trả lời ở trên được không?
Xogno

1
Giải pháp này không sửa đổi phần tử ban đầu nhưng trả về một mảng mới với mục nhập đang được di chuyển.
chmanie

7

Thay đổi 2 thành 1 làm tham số đầu tiên trong lệnh gọi mối nối khi xóa phần tử:

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

1
nó phải là playlist.splice (2,0, tmp [0]); Đúng?
Crisboot

7

Với ES6, bạn có thể làm như sau:

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
Điều này hoán đổi vị trí của hai phần tử. Câu hỏi là để sắp xếp lại.
THEO

5

Bạn luôn có thể sử dụng phương pháp sắp xếp, nếu bạn không biết bản ghi hiện tại ở đâu:

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

Còn vềreturn +(a.artist == "Lalo Schifrin")
Funkodebat

2
@Funko bạn có thể làm điều đó, nếu bạn thích ngắn gọn hơn là dài dòng.
Andy E

2

CHỈNH SỬA: Vui lòng kiểm tra câu trả lời của Andy vì câu trả lời của anh ấy xuất hiện trước và đây chỉ là phần mở rộng của anh ấy

Tôi biết đây là một câu hỏi cũ, nhưng tôi nghĩ nó đáng để đưa vào Array.prototype.sort() .

Đây là một ví dụ từ MDN cùng với liên kết

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

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

May mắn thay, nó không chỉ hoạt động với các con số:

arr.sort([compareFunction])

compareFunction

Chỉ định một hàm xác định thứ tự sắp xếp. Nếu bỏ qua, mảng được sắp xếp theo giá trị điểm mã Unicode của mỗi ký tự, theo sự chuyển đổi chuỗi của mỗi phần tử.

Tôi nhận thấy rằng bạn sắp xếp chúng theo tên:

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

lưu ý rằng nếu bạn muốn đặt chúng theo họ, bạn sẽ phải có chìa khóa cho cả hai first_name& last_namehoặc thực hiện một số phép thuật regex, điều mà tôi không thể làm được XD

Hy vọng rằng sẽ giúp :)


Đây phải là một chỉnh sửa hoặc bình luận về câu trả lời này .
Jared Smith

@JaredSmith Rất tiếc! Tôi không thấy câu trả lời của anh ấy. Tôi không có đủ điểm hoặc bất cứ điều gì để chỉnh sửa câu hỏi của anh ấy và tôi không nghĩ rằng tất cả thông tin này nên được thêm vào một bình luận. Vì vậy, cho đến khi ai đó chỉnh sửa câu hỏi của anh ấy, tôi sẽ chỉ nói thêm rằng đây là phần mở rộng cho câu trả lời của Andy E (giống như tôi nên làm).
Jaacko Torus

Tôi nghĩ bây giờ ổn rồi :)
Jared Smith

1

Thử cái này:

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

1

Nếu bạn chỉ muốn di chuyển một mục từ một vị trí tùy ý đến cuối mảng, điều này sẽ hoạt động:

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

Nếu bạn muốn di chuyển nhiều mục từ một số vị trí tùy ý đến cuối, bạn có thể thực hiện:

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

Nếu bạn muốn di chuyển nhiều mục từ một số vị trí tùy ý đến một số vị trí tùy ý, hãy thử:

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

Là một giải pháp có thể thay đổi đơn giản, bạn có thể gọi mối nối hai lần liên tiếp:

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

Mặt khác, một giải pháp inmutable đơn giản có thể sử dụng slice vì phương thức này trả về bản sao của một phần từ mảng ban đầu mà không thay đổi nó:

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

-2

Sắp xếp lại công việc của nó theo cách này

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

Tôi hy vọng điều này sẽ hiệu quả


1
Điều này bổ sung gì so với các câu trả lời hiện có?
Jared Smith
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.