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

如何使用泛型方法遵循卡牌游戏规则对混合类型卡牌数组进行排序

How to Sort Cards with Generic Methods Following Card Game Rules

Hey there! Let's start by addressing why your original code worked by coincidence: the default Array.sort() converts all elements to strings and compares their UTF-16 code values. In your specific case, numeric strings like "2" come before "Jack", and "Jack" < "Queen" < "King" lexicographically—this just happened to match your expected output. But this approach is fragile (for example, "10" would sort before "2" because "1" has a lower code value than "2").

To fix this properly and add generic support for type safety/reusability, here's a step-by-step solution:

1. Define a Clear Card Type (for Type Safety)

First, we'll define a type that represents valid cards—either numbers or the specific face cards. This helps catch invalid values early and enables proper generic constraints.

2. Create a Weight Mapping

Assign numeric weights to face cards so we can compare all cards consistently. Numbers use their own value as weight, while face cards follow the order Jack < Queen < King.

3. Build the Generic Sort Function

The generic function will accept an array of cards, enforce type constraints, and use a custom comparator based on our weight mapping to sort correctly.

TypeScript Implementation

// Define valid card types
type Card = number | 'Jack' | 'Queen' | 'King';

// Map face cards to numeric weights for consistent comparison
const cardWeights: Record<Exclude<Card, number>, number> = {
  Jack: 11,
  Queen: 12,
  King: 13
};

/**
 * Sorts an array of cards following standard card game rules
 * @param cards Array of valid cards to sort
 * @returns New sorted array (original array remains unchanged)
 */
function sortCards<T extends Card>(cards: T[]): T[] {
  // Create a copy to avoid mutating the original array
  return [...cards].sort((a, b) => {
    // Get weight for each card
    const weightA = typeof a === 'number' ? a : cardWeights[a];
    const weightB = typeof b === 'number' ? b : cardWeights[b];
    
    // Compare weights to sort ascending
    return weightA - weightB;
  });
}

// Test the function
const cards: Card[] = ['Jack', 8, 2, 6, 'King', 5, 3, 'Queen'];
const sortedCards = sortCards(cards);
console.log(sortedCards); // Output: [2, 3, 5, 6, 8, 'Jack', 'Queen', 'King']

JavaScript Implementation (with JSDoc Generics)

If you're using plain JavaScript, you can still add generic type hints via JSDoc for better IDE support:

/**
 * Sorts an array of cards following standard card game rules
 * @template {number | 'Jack' | 'Queen' | 'King'} T
 * @param {T[]} cards Array of valid cards to sort
 * @returns {T[]} New sorted array (original array remains unchanged)
 */
function sortCards(cards) {
  const cardWeights = {
    Jack: 11,
    Queen: 12,
    King: 13
  };
  
  return [...cards].sort((a, b) => {
    const weightA = typeof a === 'number' ? a : cardWeights[a];
    const weightB = typeof b === 'number' ? b : cardWeights[b];
    return weightA - weightB;
  });
}

// Test the function
const cards = ['Jack', 8, 2, 6, 'King', 5, 3, 'Queen'];
console.log(sortCards(cards)); // Output: [2, 3, 5, 6, 8, 'Jack', 'Queen', 'King']

Key Benefits of This Approach

  • Correctness: No longer relies on accidental string ordering—sorting is based on explicit card game rules.
  • Type Safety: The generic constraint T extends Card ensures only valid cards are passed to the function, preventing bugs from invalid values.
  • Immutability: We create a copy of the array before sorting, so the original array isn't modified (a best practice for predictable code).
  • Extensibility: Adding new card types (like "Ace") is easy—just update the Card type and cardWeights mapping.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 17:54:07