3

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}
]
3
  • if you're wanting to use lodash intersection, you can use _.intersectionBy or _.intersectionWith. The second is probably better for your use case Commented Dec 18, 2019 at 15:41
  • You'll have to write a custom function for _.intersectionWith that only compares the properties you want to, or alternatively compares all the properties except the ones you don't want to. Commented Dec 18, 2019 at 15:41
  • I tried but it is not working. However I can use also different functions Commented Dec 18, 2019 at 15:43

2 Answers 2

2

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>

Sign up to request clarification or add additional context in comments.

Comments

0

To create an intersection with a custom behaviour, use _.intersectionWith(). The method accepts a predicate that compares between two objects. In this case the comparison is almost identical to _.isEqual(), but it should ignore a property.

You can create the predicate with _.isEqualWith(), which accepts a customizer function. If the compared key (the 3rd param) is foot it should return true (equal because we don't care), if not it should return undefined so that _.isEqualWith() can make the standard _.isEqual() comparisons.

const 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 }];
const b = [{ weight: '75', height: '170', foot: '', available: true }, { weight: '93', height: '201', foot: '', available: true }, { weight: '65', height: '163', foot: '', available: false }];

const result = _.intersectionWith(a, b, 
  _.partialRight(_.isEqualWith,
    (...args) => args[2] === 'foot' ? true : undefined
  )
);

console.log(result);
.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>

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.