1

I can't figure out why the sort function doesn't sort the array containing undefined.

var sortBy = function(collection, iterator) {
    var newArr = map(collection, function(item, key, collection) {

        if (item === undefined, null) {
            return [undefined, undefined];

        } else {
            if (typeof(iterator) === 'string') {
                return [item, item[iterator]];

            } else {
                var results = iterator(item);
                return [item, results];
            }
        }
    });

    newArr.sort(function(a, b) { 
        return a[1] - b[1];
    });

    return map(newArr, function(item, key, collection) {
        return  item[0];
    });
};

var list = [4, 1, undefined, 3, 2];
sortBy(list, function(i) { return i; });

If i remove the undefined, the array sorts just fine. With it, it doesn't sort at all. Thanks for your help! (PS I'm new to coding so any other tips/recs on this are welcome)

2
  • 4
    Maybe if(item === undefined, null){ should be if(item === undefined || item === null){. Commented Jan 22, 2014 at 2:50
  • 1
    if(item==null) covers both null and undefined in one fell swoop. Commented Jan 22, 2014 at 2:54

2 Answers 2

2

Presuming the map function is something like:

function map(obj, fn) {
  var re = /^\d+$/;
  var arr = [];

  for (var p in obj) {
    if (re.test(p) && obj.hasOwnProperty(p)) {
      arr.push(fn(obj[p], p, obj)); 
    }
  }
  return arr;
}

then in the sort function, the statement:

return a[1] - b[1];

will do things like:

4 - undefined => NaN

So the erroneous line in the iterator could be:

    if (item === undefined || item === null) {
        return [undefined, 0];
    }

or whatever value you wish undefined and null to be sorted using—Infinity perhaps?

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

1 Comment

thanks! The map is _.map in underscore but written in JS for this project. For var re, what does that mean?
0
if (item === undefined, null)

does never fulfill - it's using the comma operator. You want if (item == null), which will test for both undefined and null.

However, since your iterator in the example is the identity function, this bug does not matter and newArr looks as expected.


return a[1] - b[1];

If one of the values is undefined, the result of the subtraction will be NaN - which is not a valid return value for a compare function. If such happens, the sort behavior is unspecified - it could be (implementation-dependent) anything from screwing up the order, not sorting at all or even never terminate. See also this answer and the relevant spec section.

So choose where you want to place undefined values in the result array, and put a comparable value for the desired position in your tuple (array). Maybe Infinity or -Infinity?

1 Comment

After thinking about it, perhaps [null, Math.MAX_VALUE] and [undefined, Infinity] so they sort per Array.prototype.sort. :-)

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.