'Sort the array as per the rules of card game using a generic method

cards = ['Jack', 8, 2, 6, 'King', 5, 3, 'Queen', "Jack", "Queen", "King"] <!- Required Output = [2,3,5,6,8,'Jack','Queen','King'] Question: Sort the array as per the rules of card game using a generic method.



Solution 1:[1]

One approach is to use an array with all the cards in the right order as a reference, and rank each card being sorted by its index in the reference array.

let cards = ['Jack', 8, 2, 6, 'King', 5, 3, 'Queen',"Jack","Queen","King"];

// change this to match the rules of card game
let theRightOrder = ["Ace", 2, 3, 4, 5, 6, 7, 8, 9, 10, "Jack", "Queen", "King"];

cards.sort((a, b) => theRightOrder.indexOf(a) - theRightOrder.indexOf(b));

console.log(cards);

Solution 2:[2]

The required output to this problem has to be displayed in an ascending order. Other items greater than 10 (Jack, Queen, King) are limited, so we can attach a weight to each of them.

let cards = ['Jack', 8, 2, 6, 'King', 5, 3,"Queen"];
// change this to match the rules of card game

const otherItems = {
'Jack': 11,
'Queen': 12
'King': 13
}

cards.sort((a, b) => {
if(isNaN(a)) a = otherItems[a];
if(isNaN(b)) b = otherItems[b];
return a-b;
});

console.log(cards);

Instead of looking for index in an array, items with weight greater than 10 can be looked up on otherItems

Solution 3:[3]

let cards = ['Jack', 8, 2, 6, 'King', 5, 3, 'Queen', "Jack", 
             "Queen","King"]
const otherItems = {
'Ace':1,
'Jack': 11,
'Queen': 12,
'King': 13
}


const solutionTwo= (someArray)=>{

someArray.sort((a,b)=>{
    a= isNaN(a)? otherItems[a]:a;
    b= isNaN(b)? otherItems[b]:b;
    return a-b;
});

console.log("Solution Two array", someArray);
}

solutionTwo(cards);

Solution 4:[4]

This is unrelated language but if anyone wants to solve this using python, here is the code i came up with during an interview that asked for the same solution with 3 different test cases.

def test_case(cards):
    int_list = sorted([x for x in cards if type(x) == int])
    str_list = sorted([x for x in cards if type(x) == str])
    for x in str_list:
        if x == "King":
            str_list.remove(x)
            str_list.append(x)
    sorted_cards = int_list + str_list
    print(f"TEST CASE = {sorted_cards}")

    test_case(['Jack', 8, 2, 6, 'King', 5, 3, 'Queen'])
    test_case(['Jack', 8, 2, 6, 'King', 5, 3, 'Queen', 'Jack', 'King', 'Queen', 'Queen', 'King', 'Jack'])
    test_case(['Jack', 8, 2, 6, 5, 3])

Solution 5:[5]

This solution avoids mutating the original array and instead provides a shallow-copy of the cards in the sorted-order. It allows being called with parameters to indicate whether:

a. Ace is low (default) or high

b. Duplicates need to be removed (default) or retained

c. The sorted array needs to be ascending (default) or descending

const handleDupes = (fl, ar) => (fl ? [...new Set(ar)] : ar);

const sortCards = (arr, aceHigh = false, removeDupes = false, descending = false) => {
  const sorted = [...Array(9)].map(
    (x, i) => (i + 2)
  ).concat(
    "Jack, Queen, King".split(', ')
  );
  if (aceHigh) sorted.push("Ace");
  else sorted.splice(0, 1, "Ace");
  return handleDupes(
    removeDupes, 
    [...arr]
    .sort(
      (a, b) => (
        sorted.indexOf(a) > sorted.indexOf(b)
        ? descending ? -1 : 1
        : descending ? 1 : -1
      )
    )
  );
};

const unsorted = ['Jack', 8, 2, 6, 'King', 5, 3, 'Queen', "Jack", "Queen", "King"];

console.log(sortCards(unsorted, true, true));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 James
Solution 2 Devmaleeq
Solution 3 Eze Onyekachukwu
Solution 4
Solution 5