xShirase
xShirase

Reputation: 12399

Compare array with sorted Array, pick first element

The setup is the following :

targets = ['green','orange','red'];  //targets are in order of priority
sources = ['redalert','blackadder','greenlantern'];

I am trying to make a function that returns the one source element which contains the highest priority target string. In this case, it would be 'greenlantern', as it contains the string 'green', which has higher priority than 'red' found in 'redalert'.

I have done it already using for loops and temp arrays, but I know these manipulations aren't my forte, and my real-life arrays are way larger, so I'd like to optimize execution. I have tried with Lodash too, but can't figure out how to do it all in one step. Is it possible?

The way I see it, it has to :

but I'm sure there's a better way.

Upvotes: 3

Views: 345

Answers (2)

Adam Boduch
Adam Boduch

Reputation: 11211

Here's another lodash approach that uses reduce() instead of sortBy():

_.reduce(targets, function(result, target) {
    return result.concat(_.filter(sources, function(source) {
        return _.includes(source, target);
    }));
}, []);

Since targets is already in order, you can iterate over it and build the result in the same order. You use reduce() because you're building a result iteratively, that isn't a direct mapping.

Inside the reduce callback, you can concat() results by using filter() and includes() to find the appropriate sources.


This gets you the sorted array, but it's also doing a lot of unnecessary work if you only want the first source that corresponds to the first target:

_.find(sources, _.ary(_.partialRight(_.includes, _.first(targets)), 1));

Or, if you prefer not to compose callback functions:

_.find(sources, function(item) {
    return _.includes(item, _.first(targets));
});

Essentially, find() will only iterate over the sources collection till there's a match. The first() function gets you the first target to look for.

Upvotes: 1

moonwave99
moonwave99

Reputation: 22817

Keeping it very simple:

var sortedSources = _.sortBy(sources, function(source){
  var rank = 0
  while(rank < targets.length){
    if(source.indexOf(targets[rank]) > -1){
      break
    }else{
      rank++
    }
  }
  return rank
})

Sources are now sorted by target priority, thus sortedSources[0] is your man.

Upvotes: 1

Related Questions