0

I'm making Rummy. I need to get all objects that match two object properties, card suit and card value in two sets of arrays.

Array A:

[
   {
      suit : 'spades',
      value : 13
   },
   {
      suit : 'hearts',
      value : 8
   },   
   ...
]

Array B

[
   {
      suit : 'spades',
      value : 11
   },
   {
      suit : 'hearts',
      value : 8
   },   
   ...
]

Result would be an Array:

[
   {
      suit : 'hearts',
      value : 8
   },   
]

I found this SO post on using functional programming and grouping, then using for in to check equality:

An efficient way to get the difference between two arrays of objects?

However this seems to be based on a single property.

So I tried:

var test_hand = testHand(Control_Panel.test_hand);
var bValues = {};
test_hand.forEach(function (test_card) {
    bValues[test_card.value] = test_card;
    bValues[test_card.suit] = test_card;
});
var tester = this.deck.filter(function (card) {
    return (card.value in bValues) && (card.suit in bValues);
});

But obviously this is going to return 2x as many cards.

Any thoughts?

Community
  • 1
  • 1
user3871
  • 12,432
  • 33
  • 128
  • 268

2 Answers2

2

Try this:

var a = [{
    suit: 'spades',
    value: 13
}, {
    suit: 'hearts',
    value: 8
}];

var b = [{
        suit: 'spades',
        value: 11
    }, {
        suit: 'hearts',
        value: 8
    },

];

var result = a.filter(function(v) {
    return b.filter(function(v2) {
        return (v.suit === v2.suit && v.value === v2.value);
    }).length > 0;
});

console.log(result);

Output:

enter image description here

Will
  • 1,718
  • 3
  • 15
  • 23
1

A different approach would be to create a hash where the key is the combination of the suit and the value:

var a = [{
    suit: 'spades',
    value: 13
}, {
    suit: 'hearts',
    value: 8
}];

var b = [{
        suit: 'spades',
        value: 11
    }, {
        suit: 'hearts',
        value: 8
    }];

var hash = {};
var key = function (el) { return el.suite + '-' + el.value; };
b.forEach(function (el) { hash[key(el)] = true; });

// intersection between a and b
var intersection = a.filter(function (el) { return hash[key(el)]; });

// elements in a that are not in b -- removes all cards in a that are present in b
var aMinusB = a.filter(function (el) { return !hash[key(el)]; });
Jaime
  • 6,736
  • 1
  • 26
  • 42
  • I mean, I need to basically splice out of `A` all cards that are in `B`. Sorry for the confusion!! – user3871 Dec 23 '15 at 05:14
  • Shouldnt it be as simple as `return (test_card.suit !== deck_card.suit && test_card.value !== deck_card.value);` – user3871 Dec 23 '15 at 05:16
  • So aMinusB returns has the cards that are in A that are not in B (A-B), the difference with this approach is in performance, with Will's approach you're basically looping all the elements in one array for each element in the other array (O(n2)) with this approach you are looping only each array once (O(n)) at the expense of some extra memory needed – Jaime Dec 23 '15 at 05:22