6

I already read the previous questions answered, but it didn't fit with my need.

I have an array of objects such as

var Widgets = [
             [{Id: 'abcdef', post_id: 12345}],
             [{Id: 'ghijkl', post_id: 45678}],
             [{Id: 'mnoptq', post_id: 90123}]
];

I have a second array :

var sortArray = ['ghijkl', 'mnoptq', 'abcdef'];

I need To reorder Widgets with the initial order of elements which appears on sortArray

i've succeed to do it this way

sortArray.forEach(function(Id) {
                    var found = false;                  
                    Widgets = Widgets.filter(function(Widget) {
                        if(!found && Widget.Id == Id) {
                            NewWidgets.push(Widget);
                            found = true;
                            return false;
                        } else {
                            return true;
                        }
                    });
                });

But I wish to improve this code by using _SortBy but I didn't succeed so far...

Anyhelp ?

Edit

Final result should be

var Widgets = [
             [{Id: 'ghijkl', post_id: 45678}],
             [{Id: 'mnoptq', post_id: 90123}],
             [{Id: 'abcdef', post_id: 12345}]
];
3
  • 3
    This is unclear, the array has no order, it's all the same ? Commented Feb 23, 2015 at 12:19
  • @Toucouleur what result do you want ? Commented Feb 23, 2015 at 12:20
  • Sorry I made a mistake on copy/paste, info added Commented Feb 23, 2015 at 12:26

2 Answers 2

5

Like this?

sorted = _.sortBy(Widgets, function(x) {
    return _.indexOf(sortArray, x[0].Id)
})

This is not very efficient, a faster way is to convert sortArray to an object key=>index and use hash lookups in sortBy:

sortObj = _.invert(_.object(_.pairs(sortArray)));

sorted = _.sortBy(Widgets, function(x) {
    return sortObj[x[0].Id]
})
Sign up to request clarification or add additional context in comments.

2 Comments

Works like a charm even if I made this change to fit with my needs : sortArray = _.invert(_.object(_.pairs(sortArray))); Widgets = _.sortBy(Widgets, function(Widget) { return sortArray[Widget.objectId]; });
I had to add parseInt to make this work properly. I'm pretty sure it's because my sort array was > 10 items and the sortObj was a collection of strings. So: return parseInt(sortObj[x[0].Id]), 10)
0

On top of @georg's solution, if performance is really important to you, and you have to keep something like this1, then preparing the key/index object using the following will be much faster:

// Example: ['a', 'b', 'c'] becomes { 'a': 0, 'b': 1, 'c': 2 }
var sortObj = sortArray.reduce(function(acc, value, index) {
  acc[value] = index;
  return acc;
}, {});

// Same as posted by @georg, with no need for `parseInt`
sorted = _.sortBy(Widgets, function(Widget) {
  return sortObj[Widget[0].Id];
});

It's a bit longer but also I'd argue it's also easier to read than the invert/object/pairs.

Also, note that there is no need for parseInt with this solution, because it builds an object of integer values, while the other solution returns strings.

1 Because let's face it, there are other ways to improve this if you actually can give it a bigger refactor.

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.