jQuery: используйте фильтр (), но работа с обоими результатами

В jQuery, filter() уменьшает Ваш результат до тех элементов, которые выполняют определенное условие.

Это разделяет список в двух частях. Работа с "хорошей половиной" элементов легка:

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

Но как может я работать с "другой половиной" моих элементов, также - но не делая эквивалента этого:

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

В основном я хотел бы подать два отдельных /* do something */ части к единственному фильтру. Один для тех, которые соответствуют, и один для других - не имея необходимость фильтровать дважды. Я пропускаю функцию jQuery, которая делает это?


P.S.: Я предполагаю, что мог сделать:

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

Но я надеялся на что-то более хорошее.

13
задан Tomalak 11 June 2010 в 18:18
поделиться

6 ответов

Метод, рекомендованный Коби в форме плагина:

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

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

Обратите внимание, что invert () не добавит новый элемент в стек jQuery, а заменит последний:

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

Изменить: изменил prevObject на end () по предложению Томалака.

16
ответ дан 1 December 2019 в 20:42
поделиться

Не знаю, лучше ли это, но с помощью filter () вы могли бы сделать что-то вроде:

var $others = $();

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

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

РЕДАКТИРОВАТЬ:

Сначала я попробовал, начав с пустого набора jQuery. $ () , а затем с помощью add () заполнить его результатами без фильтрации, но не смог заставить его работать.

РЕДАКТИРОВАТЬ:

Обновлено для использования push непосредственно на пустой объект jQuery, как было предложено Томалаком .

1
ответ дан 1 December 2019 в 20:42
поделиться
$.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
});

Я не уверен, что это удобнее для чтения, чем вставка if внутри каждого вручную.

1
ответ дан 1 December 2019 в 20:42
поделиться

Я обычно использую not для этого - он может взять массив элементов и удалить их из вашего выбора, оставив вам дополнение:

var all = $("some selector");
var filtered = all.filter(function() {
  // determine result...
  return result;
});
var others = all.not(filtered);
10
ответ дан 1 December 2019 в 20:42
поделиться

Вы можете попробовать написать плагин jQuery для этого. Посмотрите код функции filter и придумайте что-то, что делает более точно то, что вы хотите. Это может быть что-то вроде:

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

Затем вы передадите три обратных вызова: один, который оценивает объект, чтобы увидеть, соответствует ли он выбору фильтра (вы также можете принять строку селектора, или что-то подобное); один, который обрабатывает объекты, соответствующие выбору, и другой, который обрабатывает объекты, которые не соответствуют.

1
ответ дан 1 December 2019 в 20:42
поделиться

Интересный вопрос. Я вижу, что вы склоняетесь к тому, что я собирался предложить:

$("some selector").each(function() { 
  if ($(this).is(SOMEFILTER)) { 
    // do something
  } else {
    // do something  
  }
  // continue with things that apply to everything
}); 
0
ответ дан 1 December 2019 в 20:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: