javascript - xóa phần tử mảng với điều kiện


77

Tôi đã tự hỏi làm thế nào tôi sẽ thực hiện một phương thức trong javascript để loại bỏ tất cả các phần tử của một mảng xóa một điều kiện nhất định. (Tốt hơn là không sử dụng jQuery)

Ví dụ.

ar = [ 1, 2, 3, 4 ];
ar.removeIf( function(item, idx) {
    return item > 3;
});

Ở trên sẽ đi qua từng mục trong mảng và loại bỏ tất cả những return truemục cho điều kiện (trong ví dụ, mục> 3).

Tôi chỉ mới bắt đầu với javascript và tự hỏi liệu có ai biết cách hiệu quả ngắn để hoàn thành việc này không.

- cập nhật -

Nó cũng sẽ rất tốt nếu điều kiện cũng có thể hoạt động trên các thuộc tính đối tượng.

Ví dụ.

ar = [ {num:1, str:"a"}, {num:2, str:"b"}, {num:3, str:"c"} ];
ar.removeIf( function(item, idx) {
    return item.str == "c";
});

Mục sẽ bị xóa ở đâu nếu item.str == "c"

- update2 -

Sẽ rất tốt nếu các điều kiện chỉ mục cũng có thể hoạt động.

Ví dụ.

ar = [ {num:1, str:"a"}, {num:2, str:"b"}, {num:3, str:"c"} ];
ar.removeIf( function(item, idx) {
    return idx == 2;
});

Câu trả lời:


50

Bạn có thể thêm phương pháp của riêng mình để Arraythực hiện điều gì đó tương tự, nếu filterkhông hiệu quả với bạn.

Array.prototype.removeIf = function(callback) {
    var i = 0;
    while (i < this.length) {
        if (callback(this[i], i)) {
            this.splice(i, 1);
        }
        else {
            ++i;
        }
    }
};

Đối với tôi, đó là một trong những tính năng thú vị nhất của JavaScript. Ian đã chỉ ra một cách hiệu quả hơn để làm điều tương tự. Xét rằng đó là JavaScript, mọi bit đều giúp:

Array.prototype.removeIf = function(callback) {
    var i = this.length;
    while (i--) {
        if (callback(this[i], i)) {
            this.splice(i, 1);
        }
    }
};

Điều này giúp tránh phải lo lắng về việc cập nhật lengthhoặc bắt các mục tiếp theo, khi bạn làm việc theo cách của bạn sang trái thay vì phải.


Cảm ơn, hoạt động tuyệt vời. Tôi thích cách điều này xem xét các thay đổi chỉ mục thông qua việc nối trong quá trình lặp lại.
dk123

4
Đó là một chút lộn xộn. Hãy thử jsfiddle.net/n8JEy/4 - và bạn đã không chuyển iđến lệnh gọi lại như là tham số thứ hai
Ian

@ Tôi có xu hướng thích tính dễ đọc hơn, nhưng giải pháp của bạn chắc chắn hiệu quả hơn. Tôi cũng đã thêm chỉ mục làm tham số thứ hai (chỉ đơn giản là bỏ qua nó ban đầu vì nó không được sử dụng và tôi cho rằng anh ấy không cần nó).
kén chọn

@ dk123 Là một người mới sử dụng JavaScript, bạn có thể tự do kiểm soát các tham số của các lệnh gọi lại như vậy khi bạn thấy phù hợp và bạn có thể thêm bất cứ thứ gì bạn muốn vào chúng miễn là có sẵn thông tin (ví dụ: bạn có thể thêm độ dài của mảng hiện tại bằng cách sử dụng this.lengthnhư một tham số thứ ba, nếu bạn có một số độ nghiêng).
kén chọn vào

@pickypg Không sao! Điều đó chắc chắn đúng. Tôi đoán tôi không thấy lý do gì để tách logic theo cách đó, nhưng rõ ràng là ổn. Và "lộn xộn" là thuật ngữ sai khi sử dụng. Không nhận ra về thông số thứ hai, chỉ muốn chỉ ra nó :)
Ian

94

Bạn có thể sử dụng phương pháp lọc Mảng .

Mã sẽ như thế này:

ar = [1, 2, 3, 4];
ar = ar.filter(item => !(item > 3));
console.log(ar) // [1, 2, 3]


47
Nếu bạn dịch !(item > 3)sang ngôn ngữ của con người, nó sẽ được item <= 3.
Miha_x64

5
Hãy nhớ rằng phương thức Array.filter tạo ra một mảng mới. Nếu bạn tham chiếu mảng của mình trong một biến khác, tham chiếu sẽ bị hỏng sau đó: ar1 = [1, 2, 3, 4]; ar2 = ar1; ar1 = ar1.filter(item => !(item > 3)); console.log(ar1); console.log(ar2);
Atilla Baspinar

37

Bạn có thể sử dụng Array.filter(), điều này ngược lại:

ar.filter(function(item, idx) {
    return item <= 3;
});

2
Như một phần đầu không được hỗ trợ trong IE8 trở xuống. Bạn cũng nên phủ định biểu thức ban đầu, hoặc nó phải như vậy <=.
kén chọn

17
Array.filter () không trả về một mảng mới với các phần tử đã lọc? Có thứ gì đó chỉ xóa các phần tử khỏi mảng không?
dk123

@ dk123: Không có gì được tạo trước. Bạn sẽ phải viết một forvòng lặp.,
Máy xay sinh tố

Tạo một mảng mới với Array.filtercó thể sẽ nhanh hơn so với việc nối thủ công ra khỏi mảng đã cho.
Casey Chu

1
@Blender Điều đó rất thú vị. Tôi thề là tôi vừa xem xét một cái gì đó gần đây để so sánh hai và nó là trái ngược. Bình luận ngu ngốc của tôi đã bị xóa. Cảm ơn bạn đã cung cấp điều đó để làm bằng chứng :)
Ian

5

Bạn có thể sử dụng lodash.remove

var array = [1, 2, 3, 4];
var evens = _.remove(array, function(n) {
  return n % 2 == 0;
});

console.log(array);
// => [1, 3]

console.log(evens);
// => [2, 4]

2

Tôi thích những loại câu hỏi này và chỉ là một phiên bản khác với tôi ... :)

Array.prototype.removeIf = function(expression) {
   var res = [];
    for(var idx=0; idx<this.length; idx++)
    {
      var currentItem = this[idx];
        if(!expression(currentItem))
        {
            res.push(currentItem);
        }
    }
    return res;
}

ar = [ 1, 2, 3, 4 ];
var result = ar.removeIf(expCallBack);


console.log(result);
function expCallBack(item)
{
    return item > 3;
}

1
Bạn có thể sửa đổi (hoặc thêm một phương thức khác) mã của mình một chút để thực sự loại bỏ các phần tử thay vì trả về một mảng mới không? Cảm ơn vi đa trả lơi.
dk123

3
bất cứ ai phản đối điều này rất sai lầm. đây là câu trả lời hoàn hảo nhất trong số tất cả chúng. kiểm tra bài kiểm tra bằng @Blender jsperf.com/splice-vs-filter. nó nhanh hơn ít nhất 2 lần và nhanh hơn 15 lần trong các phiên bản mới nhất của Firefox
quốc hội

2

chỉ cần viết ví dụ sau nếu điều kiện cũng có thể hoạt động trên các thuộc tính đối tượng

var ar = [ {num:1, str:"a"}, {num:2, str:"b"}, {num:3, str:"c"} ];
var newArray = [];
for (var i = 0, len = ar.length; i<len; i++) {
        if (ar[i].str == "b") 
        {newArray.push(ar[i]);};
 };
console.log(newArray);

Xem ví dụ về Live Example


2

Biến nó thành một lớp lót với chức năng mũi tên:

ar = ar.filter(i => i > 3);
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.