Как мне отменить фильтр в javascript?

#javascript #arrays #filter

#javascript #массивы #Фильтр

Вопрос:

Как бы я написал функцию «reverse», которая фильтровала бы элементы, не отфильтрованные исходным фильтром? Я чувствую, что это должно быть просто, но я не могу придумать решение.

 let f1 = e => e > 3;

let f2 = reverse(f1);

let filteredarr = [1, 2, 3, 4, 5].filter(f2);

console.log(filteredarr); // prints [1, 2, 3]
 

Комментарии:

1. Добро пожаловать в SO! Вы можете попробовать отрицать логическое значение текущего фильтра… В качестве отступления рассмотрим более описательные имена функций, чем f1 и f2 . reverse не отображается, поэтому не совсем понятно, что он делает, хотя возможно, что он отрицает результат параметра функции. Если это так, то не используйте его, и вы получите противоположное f2 .

2. @ggorlen Я думаю, OP хочет знать, как reverse это должно быть реализовано. Я не верю, что он еще существует.

Ответ №1:

У меня такое чувство, что вы ищете функцию более общего назначения, которой вы можете передать любую другую функцию. В этом случае это немного сложнее, но не очень.

 // Perhaps opposite is a better name, since .reverse already exists
const opposite = f => ((...args) => !f(...args));

const predicate = e => e > 3;
const arr = [1, 2, 3, 4, 5];

console.log(arr.filter(predicate));
console.log(arr.filter(opposite(predicate))); 

По сути, opposite это функция, которая возвращает другую функцию, и возвращаемое значение возвращаемой функции является логическим отрицанием возвращаемого значения первой функции.

Это ... называется синтаксисом распространения, и в этом случае он сообщает JavaScript как принимать произвольное количество аргументов, так и отправлять через то же произвольное количество параметров.


Конечно, если вы не ищете решение общего назначения, то более простой путь — просто отрицать возвращаемое значение вашей функции на месте в .filter вызове:

 const predicate = e => e > 3;
const arr = [1, 2, 3, 4, 5];

console.log(arr.filter(predicate));
console.log(arr.filter((...args) => !predicate(...args))); 

Комментарии:

1. Возможно, здесь было бы лучше использовать rest-параметры на случай, если предикат принимает больше аргументов, отличных от только текущего элемента (например, индекса), например: const opposite = fn => (...args) => !fn(...args);

2. @NickParsons Хорошая мысль, как я мог забыть? Я обновлю свой ответ. Спасибо!

3. Чувак, вы, ребята, такие классные. Хотел бы я быть таким же умным, как вы, ребята.

Ответ №2:

Это работает, но я не знаю, это именно то, что вы ищете.

 // Predicate
const isLargerThan3 = number => number > 3;

const reversePredicate = predicate => number => !predicate(number);

const filteredArray = [1, 2, 3, 4, 5].filter(reversePredicate(isLargerThan3));

console.log(filteredArray);