Reputation: 12399
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 :
for each target, loop through sources, if source elem matches target elem, break and return.
but I'm sure there's a better way.
Upvotes: 3
Views: 345
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
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