0

Straightforward question:

Can I negate a callback function that returns true or false o an array.filter() statement? e.g.

//the callback function
function isEven(element, index, array){
    if (index%2 == 0 || index == 0){
        return true;
    }
    return false;
}

//what i want to do with that function
//arr[i] is a string
var evens = arr[i].split("").filter(isEven); //works
var odds = arr[i].split("").filter(!isEven); // doesn't work

the above line gives me the error TypeError: false is not a function

Question with some background:

I'm taking on some Hackerrank challenges and i've come across an exercise that requires to take a string and process it, so the output is: The characters with even index values make a new string and the characters in odd index positions make another string , 0 counts as even.

Input

airplane

Output

evens = 'arln'

odds = 'ipae'

I have already solved it by looping through the string, evaluating the index and then pushing the value to the correspondent new array (which i later convert to a string), but it has occurred to me i could be done in a more functional way, using the Array.prototype.filter() function.

now I create a new function that evaluates whether the index number is even or not, and I'd like to use that same function to fill both arrays (evens and odds), like this (now you can refer to the straightforward question part):

var evens = arr[i].split("").filter(isEven); //works
var odds = arr[i].split("").filter(!isEven); // doesn't work

3 Answers 3

2

The simplest way to do this would be to just pass an anonymous function which returns the negated result of isEven.

var evens = arr[i].split("").filter(function(el, index, array) {
  return !isEven(el, index, array);
});

But you could take this a step further and write a not function which essentially generates the anonymous function for you. Here's an example of such a function.

var input = [0, 1, 2, 3, 4, 5];
function isEven(value) {
  return value % 2 === 0;
}
function not(f) {
  return function() {
    return !f.apply(null, arguments);
  }
}

var output = input.filter(not(isEven));
console.log(output);

If you're in an environment that supports rest parameters then you could write your not function like this.

var input = [0, 1, 2, 3, 4, 5];
function isEven(value) {
  return value % 2 === 0;
}
function not(f) {
  return function(...args) {
    return !f.apply(null, args);
  }
}

var output = input.filter(not(isEven));
console.log(output);

Sign up to request clarification or add additional context in comments.

2 Comments

thanks! I like that function not(f) a lot, it's pretty clever, is that something often used?
@randomguy04 In functional programming, that general idea is used a lot. It's known as composition and is really handy for manipulating datasets, just like what you're doing here.
1

You would need to pass in an anonymous function and then negate isEven in there:

var odds = arr[i].split("").filter(function(a, index, array) {
  return !isEven(a, index, array);
});

Simple Example:

Working Example

function isEven(n) {
  return n % 2 === 0;
}

var arr = [0,1,2,3,4,5,6,7,8,9];

var a = arr.filter(isEven);

var b = arr.filter(function(a) {
  return !isEven(a);
});

Comments

0

The solution I use is something like this:

var numbers = [0,1,2,3,4,5];
var evens = [];
var odds = [];

function isEvenOrNot(getEven) {
    return function(num) {
        if (num % 2 == 0 || num == 0){
            return true;
        }
        return false;
    }
}

evens = numbers.filter(isEvenOrNot(true));
odds = numbers.filter(isEvenOrNot(false));

console.log(evens); // [0,2,4]
console.log(odds); // [1,3,5]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.