2010-05-09 21 views
13

Trong jQuery, filter() làm giảm kết quả của bạn với những yếu tố đáp ứng một điều kiện nhất định.jQuery: sử dụng bộ lọc(), nhưng làm việc với cả hai kết quả

Việc này chia danh sách thành hai phần. Làm việc với "một nửa tốt" trong những yếu tố rất dễ dàng:

$("some selector").filter(function() { 
    // determine result... 
    return result; 
}).each(/* do something */); 

Nhưng làm thế nào tôi có thể làm việc với "nửa kia" của các yếu tố của tôi, quá - nhưng mà không làm tương đương với này:

$("some selector").filter(function() { 
    // determine result... 
    return !result; 
}).each(/* do something else */); 

Về cơ bản, tôi muốn cho hai phần riêng biệt /* do something */ vào một bộ lọc. Một cho những người phù hợp, và một cho những người khác - mà không cần phải lọc hai lần. Tôi có thiếu chức năng jQuery không?


P.S .: Tôi đoán tôi có thể làm:

$("some selector").each(function() { 
    // determine result... 
    if (result) 
    /* do something */ 
    else 
    /* do something else */ 
}); 

Nhưng tôi đã hy vọng cho một cái gì đó đẹp hơn.

+0

Tôi nghĩ rằng đó sẽ là 'mỗi()'. – Matt

+2

http://jsfiddle.net/nZtRF/ Một điều có thể đáng chú ý là với phương thức 'not()', hiệu suất giảm đi theo cấp số nhân khi số phần tử tăng lên. Đối với số lượng nhỏ hơn, nó là tầm thường. Đối với số lượng lớn, bạn sẽ nhận được hiệu suất tốt hơn bằng cách sử dụng câu lệnh 'if()' trong bộ lọc. Xem thử nghiệm tại liên kết jsfiddle ở trên, và rối tung xung quanh với số lượng. – user113716

+0

@patrick: Rất đúng. Đó là một nhược điểm nghiêm trọng. : - \ – Tomalak

Trả lời

16

Phương pháp khuyến cáo của Kobi ở dạng plugin:

$.fn.invert = function() { 
    return this.end().not(this); 
}; 

$('.foo').filter(':visible').hide().invert().show(); 

Lưu ý rằng invert() sẽ không thêm một yếu tố mới để ngăn xếp jQuery nhưng thay thế mới nhất:

$('.foo').filter(':visible').invert().end(); // this will yield $('.foo'), not $('.foo:visible') 

Edit: đã thay đổi prevObject thành end() theo đề xuất của Tomalak.

+0

Ngọt ngào. :-) Tôi thực sự thích điều đó. – Tomalak

+0

Mã của tôi không thể bị xiềng xích, và điều này dường như để có được xung quanh đó rất độc đáo. +1 – Kobi

+0

Không phải 'end()' tốt hơn 'prevObject'? 'prevObject' có nghĩa là tôi phải lọc trong bước trước ngay lập tức, trong khi' end() 'đề cập đến" hoạt động lọc gần đây nhất "theo tài liệu, điều đó có nghĩa là nó có thể là vài bước trở lại. – Tomalak

0

Câu hỏi thú vị. Tôi thấy bạn đang nghiêng về phía những gì tôi định đề xuất:

$("some selector").each(function() { 
    if ($(this).is(SOMEFILTER)) { 
    // do something 
    } else { 
    // do something 
    } 
    // continue with things that apply to everything 
}); 
+0

Tôi đã hy vọng cho một giải pháp chuỗi kiểu jQuery, phương pháp chuỗi; nhưng 'each()' sẽ hoạt động, về mặt kỹ thuật. PS: Nếu không thể xác định kết quả bộ lọc bằng bộ chọn jQuery, bạn không thể sử dụng 'is()', thật không may. – Tomalak

1

Bạn có thể thử viết một plugin jQuery để thực hiện việc này. Kiểm tra mã của bộ lọc chức năng và tìm ra thứ gì đó chính xác hơn những gì bạn muốn. Nó có thể là một cái gì đó như:

$("some selector").processList(predicate, successCallback, failureCallback); 

Sau đó, bạn sẽ vượt qua trong ba callbacks: một đánh giá một đối tượng để xem nếu nó phù hợp với lựa chọn lọc (bạn cũng có thể chấp nhận một chuỗi selector, hoặc tương tự); một trong đó xử lý các đối tượng phù hợp với lựa chọn và một đối tượng khác xử lý các đối tượng không khớp.

+0

Vâng, một cái gì đó như thế này là những gì tôi có trong tâm trí. :) Sẽ không quá phức tạp, nhưng tôi không muốn tái phát minh ra bánh xe. – Tomalak

+0

Vâng, xin lỗi. Tôi không chắc liệu có bất kỳ thứ gì tồn tại không. Nếu bạn cần trợ giúp tìm cách viết plugin, hãy cho chúng tôi biết =) – RMorrisey

+0

Cảm ơn bạn.^^ Tôi nghĩ rằng các plugin mà sẽ có thể làm điều này là không có trí tuệ. Tôi chỉ cố gắng để đảm bảo rằng tôi không thiếu một cái gì đó thông minh được xây dựng vào jQuery rồi. – Tomalak

1

Tôi không biết nếu điều này là bất kỳ đẹp hơn, nhưng sử dụng filter() bạn có thể làm một cái gì đó như:

var $others = $(); 

var $filtered = $('div').filter(function() { 
    if(! your filter test) { 
     $others.push(this); 
    } else { 
     return true; 
    } 
}); 

alert($others.length); 
alert($filtered.length); 

EDIT:

Lúc đầu, tôi đã thử nó bắt đầu với một bộ jQuery trống $(), và sau đó sử dụng add() để điền nó với kết quả không lọc, nhưng không thể làm cho nó hoạt động.

EDIT:

cập nhật để sử dụng push trực tiếp trên một đối tượng jQuery trống theo đề nghị của Tomalak.

+0

Hm, đó sẽ là một cách để làm điều đó. Không chính xác mịn, nhưng hoàn toàn khả thi. :) +1 (PS: jQuery là một mảng, bạn có thể sử dụng 'push()' trực tiếp) – Tomalak

+0

Cảm ơn, vâng, nó sẽ đẹp hơn một chút nếu tôi biết cách tốt hơn để điền tập hợp jQuery của người khác vào trong Bộ lọc. – user113716

+0

@Tomalak - chỉ nhận thấy nhận xét của bạn về việc sử dụng 'push()' trực tiếp trên đối tượng jQuery. Làm cho tinh thần, vì vậy tôi cập nhật câu trả lời của tôi. Cảm ơn. – user113716

10

Tôi thường sử dụng not cho điều này - nó có thể mất một mảng các phần tử và loại bỏ chúng khỏi lựa chọn của bạn, để lại cho bạn sự bổ sung:

var all = $("some selector"); 
var filtered = all.filter(function() { 
    // determine result... 
    return result; 
}); 
var others = all.not(filtered); 
+0

Đẹp nhất. Tôi không biết rằng 'not()' cũng hoạt động theo cách này. +1 – Tomalak

+0

+1 - Tốt hơn tôi. Cảm ơn vì tiền hỗ trợ. – user113716

+0

Thực sự rất thanh lịch. – Bora

1
$.fn.if = function(cond, ontrue, onfalse) { 
    this.each(function() { 
    if (cond.apply(this)) ontrue.apply(this); 
    else onfalse.apply(this); 
    }); 
}; 

$('some selector').if(function() { 
    // determine result 
}, function() { 
    // do something 
}, function() { 
    // do something else 
}); 

Tôi không chắc nó là nhiều hơn nữa có thể đọc được hơn là đặt một bên trong mỗi một cách thủ công, mặc dù.

+0

Bạn sẽ phải thêm chỉ mục làm đối số cho 'cond.apply()' vì chính jQuery tự cung cấp chỉ mục hiện tại cho các hàm lọc. Và bạn phải thêm kiểm tra kiểu cho các đối số 'cond, ontrue, onfalse', rõ ràng. Ngoài ra, đây là những gì tôi đã có trong tâm trí. Một khi bạn chuỗi 5 phương pháp trong jQuery, khả năng đọc bị anyway. ;) – Tomalak

Các vấn đề liên quan