2

It was hard to give it a good title to describe what this is but that's the best I came up with. Anyway, this simply creates a deck of cards and then removes the hole cards. Performance is crucial since it needs to make thousands of iterations of this new deck creation, shuffle and hole card removal.

It's very fast to create the deck but the hole card removal function has a huge performance hit since I can't find any easy way to remove an element in JS.

const suits = ['s', 'h', 'd', 'c'];
const remove = ['10s', '11s', '13h', '9c'];

var deck = mkDeck();
shuffle(deck)
rmvHole();

// Functions

function rmvHole() {
  for (let i = 0; i < remove.length; i++) {
    const key = Object.keys(deck).find(key => deck[key] === remove[i]);
    deck[key] = null;
  }
}

function mkDeck() {
  let arr = [];
  for (let s = 0; s < 4; s++) {
    for (let i = 2; i < 15; i++) {
      arr.push(i + suits[s]);
    }
  }
  return arr;
}

function shuffle(a) {
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}

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

2
  • If your suits are always going to be the same, then it would be even faster to avoid the loop and hard-code the array. And if the cards for removal are also going to be the same every time, then you can simply remove them from that hard-coded array, so you skip on looping over the entire deck at least twice. Commented Apr 2, 2019 at 4:24
  • The suits and the deck would always be the same but not the hole cards. It's for comparing hole cards against each other to determine who wins how many times etc. Commented Apr 2, 2019 at 4:44

3 Answers 3

1

Since deck should be an array, you definitely shouldn't iterate over its Object.keys - rather, since the array values are all primitives, you can identify the index with indexOf and splice, or set the item at that array index to null if that's what you want:

function rmvHole() {
    for (let i = 0, { length } = remove; i < length; i++) {
        const index = deck.indexOf(remove[i]);
        // deck.splice(index, 1);
        // deck[index] = null;
    }
}

(setting an index to null doesn't actually remove the element from the array, which is why I'm thinking you might have meant you wanted to splice instead)

const suits = ['s', 'h', 'd', 'c'];
const remove = ['10s', '11s', '13h', '9c'];

var deck = mkDeck();
shuffle(deck)
rmvHole();

// Functions

function rmvHole() {
  for (let i = 0; i < remove.length; i++) {
    const index = deck.indexOf(remove[i]);
    deck[index] = null;
  }
}

function mkDeck() {
  let arr = [];
  for (let s = 0; s < 4; s++) {
    for (let i = 2; i < 15; i++) {
      arr.push(i + suits[s]);
    }
  }
  return arr;
}

function shuffle(a) {
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}

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

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

Comments

1

If the suits are not going to change, then by far the fastest way to create this is to not have a loop, simply hard-code the array:

function mkDeck() {
  return [
      '2s', '3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', 
      '2h', '3h', '4h', '5h', '6h', '7h', '8h', '9h', '10h', '11h', '12h', '13h', '14h', 
      '2d', '3d', '4d', '5d', '6d', '7d', '8d', '9d', '10d', '11d', '12d', '13d', '14d', 
      '2c', '3c', '4c', '5c', '6c', '7c', '8c', '9c', '10c', '11c', '12c', '13c', '14c', 
  ];
}

If the cards that need to be removed are always going to be the same, then you can simply exclude them from that hard-coded array.

function mkDeck() {
  return [
      '2s', '3s', '4s', '5s', '6s', '7s', '8s', '9s',               '12s', '13s', '14s', 
      '2h', '3h', '4h', '5h', '6h', '7h', '8h', '9h', '10h', '11h', '12h',        '14h', 
      '2d', '3d', '4d', '5d', '6d', '7d', '8d', '9d', '10d', '11d', '12d', '13d', '14d', 
      '2c', '3c', '4c', '5c', '6c', '7c', '8c',       '10c', '11c', '12c', '13c', '14c', 
  ];
}

This cuts out looping over the deck several times. So all the code you're left with is:

let deck = mkDeck();
shuffle(deck);

If instead the cards for removal are dynamic, it's easier to exclude them when generating the deck, instead of looking for them after, this way you only loop over the deck once - when generating:

const suits = ['s', 'h', 'd', 'c'];
const remove = ['10s', '11s', '13h', '9c'];

var deck = mkDeck();
console.log(deck);


function mkDeck() {
  let arr = [];
  for (let s = 0; s < 4; s++) {
    for (let i = 2; i < 15; i++) {
      let card = i + suits[s];
      //only add if it should be added
      if (!remove.includes(card)) {
        arr.push(card);
      }
    }
  }
  return arr;
}

This can be even faster if remove was an object { '10s': true, '11s': true, '13h': true, '9c': true }; or a set new Set(['10s', '11s', '13h', '9c']). In either case, the lookups would not need to iterate over the entire array for each card you generate.

2 Comments

The hole cards will change each time but hardcoding the whole deck is indeed slightly faster. Strange, I looked at so many card calculator programs in php, python, and javascript and nobody ever did this. I'll look into remove being an object too and see how that goes. Thanks for your help, you seem to know a lot about speed optimisation in code.
I tried all your suggestions and the fastest was the hard encoded deck with the original remove function. Not sure why, but remove as an object doing if (!remove[card]) to remove it as the deck was created was the slowest. Removing it with deck creation with the remove as an array was faster than removing it after, but still the hard coded deck was faster still.
0

deck is an array, so you don't need Object.keys:

function rmvHole() {
    remove.forEach(r => deck.splice(deck.indexOf(r), 1));
}

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.