Mr.Ayanlar
Mr.Ayanlar

Reputation: 449

Nested collection filter with lodash

I have a collection like as below

var flights = [{
    id: 1,
    legs:[{
        carrierName:'Pegasus' 
    }]
}, {
    id: 2,
    legs:[{
        carrierName: 'SunExpress'
    },{
        carrierName: 'SunExpress'
    }]
}, {
    id: 3,
    legs:[{
        carrierName: 'Pegasus'
    },{
        carrierName: 'SunExpress'
    }]
}]

I want to filter it for example carrierName = 'Pegasus' then my result is like this

[{
    id: 1,
    legs:[{
        carrierName:'Pegasus' 
    }]
}, {
    id: 3,
    legs:[{
        carrierName: 'Pegasus'
    },{
        carrierName: 'SunExpress'
    }]
}]

Upvotes: 0

Views: 394

Answers (4)

Ori Drori
Ori Drori

Reputation: 191986

You can use Array.prototype.filter() and check each sub array using Array.prototype.some() to see if it includes the search term:

var carrierNames = ['Pegasus', 'SunExpress'];

flights.filter(function(item) {
  var predicate = this; // the carrierNames dictionary

  return item.legs.some(function(leg) {
    return predicate[leg.carrierName]; // see if carrierName exists in the dictionary
  });
}, carrierNames.reduce(function(obj, term) { // create a dictionary of carrierNames
  obj[term] = true;
  return obj;
}, Object.create(null)));

var flights = [{
    id: 1,
    legs:[{
        carrierName:'Pegasus' 
    }]
}, {
    id: 2,
    legs:[{
        carrierName: 'SunExpress'
    },{
        carrierName: 'SunExpress'
    }]
}, {
    id: 3,
    legs:[{
        carrierName: 'Pegasus'
    },{
        carrierName: 'SunExpress'
    }]
}];

var carrierNames = ['Pegasus', 'SunExpress'];

var result = flights.filter(function(item) {
  var predicate = this;
  
  return item.legs.some(function(leg) {
    return predicate[leg.carrierName];
  });
}, carrierNames.reduce(function(obj, term) {
  obj[term] = true;
  return obj;
}, Object.create(null)));

console.log(result);

And the same logic using ES6 arrow functions and parameters destructuring:

const result = flights.filter(function({ legs }) {
  const predicate = this;
  return legs.some(({ carrierName }) => predicate.has(carrierName)); // keep if carrierName is in the Set
}, new Set(carrierNames)); // create a Set from the carrierNames

const flights = [{
  id: 1,
  legs: [{
    carrierName: 'Pegasus'
  }]
}, {
  id: 2,
  legs: [{
    carrierName: 'SunExpress'
  }, {
    carrierName: 'SunExpress'
  }]
}, {
  id: 3,
  legs: [{
    carrierName: 'Pegasus'
  }, {
    carrierName: 'SunExpress'
  }]
}];

const carrierNames = ['Pegasus', 'SunExpress'];

const result = flights.filter(function({ legs }) {
  const predicate = this;
  return legs.some(({ carrierName }) => predicate.has(carrierName));
}, new Set(carrierNames));

console.log(result);

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386654

With ES6, you could use a single line for filtering, using Array#filter and Array#some.

var flights = [{ id: 1, legs: [{ carrierName: 'Pegasus' }] }, { id: 2, legs: [{ carrierName: 'SunExpress' }, { carrierName: 'SunExpress' }] }, { id: 3, legs: [{ carrierName: 'Pegasus' }, { carrierName: 'SunExpress' }] }],
    search = new Set(['Pegasus', 'SunExpress']);
    result = flights.filter(a => a.legs.some(b => search.has(b.carrierName)));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 0

Mr.Ayanlar
Mr.Ayanlar

Reputation: 449

thank you everybody. I solved it with like as below


    var airlines = ["Pegasus",SunExpress"];
    var result = _.filter(flights, function(item) {
                        return _.some(item.legs, function(leg) {
                            return _.includes(airlines, leg.carrierName);
                        });
                    });

Upvotes: 0

stasovlas
stasovlas

Reputation: 7416

just check if some legs of flight contains carrierName

_.filter(flights, function(flight) {
    return _.chain(flight)
        .get('legs')
        .map('carrierName')
        .includes('Pegasus')
        .value()
});

for check arr of values

_.filter(flights, function(flight) {
    return _.chain(flight)
        .get('legs')
        .map('carrierName')
        .thru(function(names) {
            return _.every(valuesArr, function(val) { // _.some for OR, _.every for AND
                return _.includes(names, val);
            });
        })
        .value()
});

Upvotes: 2

Related Questions