You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化JavaScript卡牌计数逻辑的链式调用实现?

问题:如何用链式调用实现Part2的功能?

我非常喜欢Part1的链式调用结构,但不得不将Part2拆分为part2Array和最终的part2变量,因为无法直接用链式调用完成逻辑。

原代码实现

const rawData = `Card 1: 41 48 83 86 17 | 83 86  6 31 17  9 48 53
 Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
 Card 3:  1 21 53 59 44 | 69 82 63 72 16 21 14  1
 Card 4: 41 92 73 84 69 | 59 84 76 51 58  5 54 83
 Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
 Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11`;

const cardObjects = (card) => {
  const cardNumber = card.match(/\d+(?=:)/)[0];
  const winningNumbers = card
    .match(/(?<=:)(.*?)(?=\|)/)[0]
    .trim()
    .split(/\s+/);
  const punterNumbers = card
    .match(/(?<=\|)(.*)/)[0]
    .trim()
    .split(/\s+/);
  return { cardNumber, winningNumbers, punterNumbers };
};

const punterWin = (card) => {
  const matchingNumber = card.winningNumbers.filter((w) =>
    card.punterNumbers.includes(w)
  );
  return matchingNumber;
};

const calculatePoints = (matchingNumber) => {
  const points = Math.pow(2, matchingNumber.length - 1);
  return points;
};

const cardWin = (wins, i) => {
  const winCount = wins.length;
  const card = i + 1;
  const cardCount = 1;
  return { card, cardCount, winCount };
};

const cardAdd = (cardWinCount, i) => {
  const winCount = cardWinCount.winCount;
  for (let x = 0; x < winCount; x++) {
    part2Array[i + x + 1].cardCount += cardWinCount.cardCount;
  }
};

// Part1 链式调用实现
const part1 = rawData
  .split(/\n/)
  .map(cardObjects)
  .map(punterWin)
  .map(calculatePoints)
  .filter((a) => a >= 1)
  .reduce((acc, cur) => acc + cur);

console.log(part1);

// Part2 拆分实现
const part2Array = rawData
  .split(/\n/)
  .map(cardObjects)
  .map(punterWin)
  .map(cardWin);

part2Array.forEach(cardAdd);

const part2 = part2Array
  .map((card) => card.cardCount)
  .reduce((acc, cur) => acc + cur);

console.log(part2);

尝试链式调用失败的代码

const part2 = rawData
  .split(/\n/)
  .map(cardObjects)
  .map(punterWin)
  .map(cardWin)
  .forEach(cardAdd)
  .map((card) => card.cardCount)
  .reduce((acc, cur) => acc + cur);

失败原因:forEach返回undefined,无法继续链式调用后续方法;同时cardAdd依赖外部的part2Array变量修改后续元素计数,没法直接嵌入链式流程。

请问有没有更简洁的Part2实现方式?


解决方案:用reduce实现链式调用

可以通过reduce维护卡片计数数组,把修改逻辑整合到链式调用中,无需外部数组变量,同时还能合并冗余步骤。

优化后的链式实现

const part2 = rawData
  .split(/\n/)
  // 合并cardObjects、punterWin、cardWin的逻辑,减少链式层级
  .map((cardStr, index) => {
    const winningNumbers = cardStr.match(/(?<=:)(.*?)(?=\|)/)[0].trim().split(/\s+/);
    const punterNumbers = cardStr.match(/(?<=\|)(.*)/)[0].trim().split(/\s+/);
    const winCount = winningNumbers.filter(num => punterNumbers.includes(num)).length;
    return { card: index + 1, cardCount: 1, winCount };
  })
  // 用reduce替代forEach,处理卡片计数的累加逻辑
  .reduce((cardList, currentCard, idx) => {
    // 根据当前卡片的赢数,给后续卡片增加计数
    for (let x = 0; x < currentCard.winCount; x++) {
      const targetIdx = idx + x + 1;
      if (targetIdx < cardList.length) {
        cardList[targetIdx].cardCount += currentCard.cardCount;
      }
    }
    return cardList;
  })
  // 汇总所有卡片的数量
  .reduce((total, { cardCount }) => total + cardCount, 0);

console.log(part2);

优化点说明

  1. 替换forEach为reduce:reduce会返回处理后的数组,能继续链式调用后续方法,解决了原链式调用中断的问题。
  2. 合并冗余步骤:把cardObjects、punterWin、cardWin的逻辑合并到一个map中,减少链式层级,提升代码效率。
  3. 移除外部依赖:无需单独定义part2Array变量,所有逻辑都在链式调用中完成,保持代码简洁。

内容的提问来源于stack exchange,提问作者Phil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:00:55