简体   繁体   English

NodeJS如何加速这个数组创建函数

[英]NodeJS how to speed up this array creation function

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.创建牌组的速度非常快,但底牌移除功能对性能造成了巨大影响,因为我找不到任何简单的方法来移除 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; }

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:由于deck应该是一个数组,你绝对不应该遍历它的Object.keys - 相反,因为数组值都是基元,你可以用indexOfsplice标识索引,或者在该数组索引处设置项目为null如果那就是你想要的:

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) (将索引设置为null实际上并没有从数组中删除元素,这就是为什么我认为您可能是想改为splice

 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; }

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 };如果remove是一个对象{ '10s': true, '11s': true, '13h': true, '9c': true }; or a set new Set(['10s', '11s', '13h', '9c']) .或一组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.在任何一种情况下,查找都不需要为您生成的每张卡片遍历整个数组。

deck is an array, so you don't need Object.keys : deck是一个数组,所以你不需要Object.keys

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM