Search code examples
javascriptarrayslodash

intersection of objects except for one attribute between two arrays


I've two arrays which contain the same kind of objects (same attributes but different values associated). I want to compare the two arrays and match the objects that are equal except for one property. Then I want to find the index of the objects-matched in the first array in order to push those objects into a different array.

I think that all of this can be made using lodash and I would like to avoid for loops, in order to make it the more efficient as possible

Note that I am working in a js class

Here's my attempt (not working)

class MatchPlayers {
    constructor(){
        this.TeamA = [
            {weight:'75',height:'170', foot:'Left', available:true},
            {weight:'88',height:'190', foot:'Right', available:true},
            {weight:'65',height:'163', foot:'Right', available:false},
            {weight:'70',height:'168', foot:'Left', available:true}
        ]

        this.TeamB = [
            {weight:'75',height:'170', foot:'', available:true},
            {weight:'93',height:'201', foot:'', available:true},
            {weight:'65',height:'163', foot:'', available:false}
        ]

        this.MatchedPlayers = []
    }

    PlayersMatch (){
        for(this.i=0;this.i<this.TeamA.length;this.i++){
            if (_.intersection(this.TeamA,{weight:this.TeamB.weight, height:this.TeamB.height, available:this.TeamB.available})){
              this.position = _.findIndex(this.TeamA,{weight:this.TeamB.weight, height:this.TeamB.height, available:this.TeamB.available})
              this.MatchedPlayers.push(this.TeamA[this.position])
            } else {console.log('No matchable players')}
          }
        console.log(this.MatchedPlayers)
    }
}

In this case I want to match the objects which have the same attributes except for "foot", so the expected output would be:

//Expected Output:
this.MatchedPlayers = [
    {weight:'75',height:'170', foot:'Left', available:true}, 
    {weight:'65',height:'163', foot:'Right', available:false}
]

Solution

  • You could take a simplified approach and omit foot property and get the intersection by _.isEqual for the lefot over properties.

    var a = [{ weight: '75', height: '170', foot: 'Left', available: true }, { weight: '88', height: '190', foot: 'Right', available: true }, { weight: '65', height: '163', foot: 'Right', available: false }, { weight: '70', height: '168', foot: 'Left', available: true }],
        b = [{ weight: '75', height: '170', foot: '', available: true }, { weight: '93', height: '201', foot: '', available: true }, { weight: '65', height: '163', foot: '', available: false }],
        omitFoot = o => _.omit(o, 'foot'),
        intersection = _.intersectionWith(
            _.map(a, omitFoot),
            _.map(b, omitFoot),
            _.isEqual
        );
    
    console.log(intersection);
    .as-console-wrapper { max-height: 100% !important; top: 0; }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>