1

I have a function to filter CSS classes for duplicates and empty spaces, but my function exports arrays with empty spaces anyway...

var classes = function (className, current) {
    var classNames = [className], uniques = {};
    if(current) classNames = classNames.concat(current.split(' '));
    return classNames.filter(function (className,i) {
        if(className == "") return;
        className = className.match(/\S+/)[0];
       if (!uniques[className]) return uniques[className] = className;
    });
};

When I run classes(' foo') I get [" foo"] with a empty space anyway, although console.log(' foo'.match(/\S+/)[0]; returns 'foo' with no space.

What am I missing?

Fiddle

2
  • 1
    What exactly are you trying to achieve? Please provide more context. Commented Jan 26, 2014 at 6:39
  • @BlackSheep, thanks for looking at this. I want to pass ' foo' into this function and get back a clean ['foo'] with no spaces. And I think I did everything correct but somewhere a empty space is being added and I can't find where... Commented Jan 26, 2014 at 6:42

1 Answer 1

4

You misunderstand how filter works. From the fine manual:

The filter() method creates a new array with all elements that pass the test implemented by the provided function.

The return value from the callback tells filter which elements of classNames should be passed through, the return value is merely tested for truthiness. The return value of the callback isn't returned by filter, the original untouched values in classNames are. So the problem isn't that an extra space is being added, the problem is that nothing is removing the spaces.

If you want to test and modify at the same time then reduce will serve you better:

return classNames.reduce(function(a, className) {
    if(!className)
        return a;
    className = className.match(/\S+/)[0];
    if(!uniques[className]) {
        a.push(className);
        uniques[className] = className;
    }
    return a;
}, []);

Note all the return a; statements and the lack of return;s.

Demo: http://jsfiddle.net/ambiguous/bw3JS/

You could also use map to clean up the spaces and then filter to clean up the undefineds with something like this:

return classNames.map(function(className) {
    if(!className)
        return;
    className = className.match(/\S+/)[0];
    if(!uniques[className])
        return uniques[className] = className;
}).filter(function(className) {
    return typeof className !== 'undefined';
});

Demo: http://jsfiddle.net/ambiguous/8j5Bb/

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

3 Comments

Aha... got the point... I'm changing the value of that iteration inside .filter() which is poinless. Good catch and thanks for a alternative solution!
I supose .map() also be a solution here. (?)
You could use map but each return value from the map callback ends up in the final array. map would leave you with undefined values or empty strings or some other value that you'd need a separate filter pass to clean up: jsfiddle.net/ambiguous/8j5Bb

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.