0

I have such an array of card objects:

const cards = [
  {
    type: { method: 'listen' },
    reference: ['destroyed', 'word 2']
  },
  {
    type: { method: 'synonym' },
    reference: ['destroyed']
  },
  {
    type: { method: 'listen' },
    reference: ['destroyed']
  },
  {
    type: { method: 'dictate' },
    reference: ['destroyed']
  }
]

I want to sort them as follows:

  1. the listen cards should come first
  2. between listen cards the ones that have less reference.length should come earlier
  3. any other cards should come then
  4. dictate cards should come at last

I have no idea how to do such a complex sorting except doing the first condition:

    cards.sort(compare);

    function compare(a, b) {
        if(a.type.method == 'listen') return a.reference.length - b.reference.length;
        ...
    }
2
  • "Any other cards should come then" - meaning their order doesn't change? Commented Nov 14, 2022 at 19:32
  • yes, exactly........ Commented Nov 14, 2022 at 19:36

3 Answers 3

1

Write out all the cases you want to do something "special" in:

const cards = [
  {
    type: { method: 'listen' },
    reference: ['destroyed', 'word 2']
  },
  {
    type: { method: 'synonym' },
    reference: ['destroyed']
  },
  {
    type: { method: 'listen' },
    reference: ['destroyed']
  },
  {
    type: { method: 'dictate' },
    reference: ['destroyed']
  }
];

cards.sort((a, b) => {
    // both types are 'dictate' - no change
    if (a.type.method === "dictate" && b.type.method === "dictate") return 0;
    // move `b` up since `a` is 'dictate'
    if (a.type.method === "dictate") return 1;
    // move `a` up since `b` is 'dictate'
    if (b.type.method === "dictate") return -1;
    
    // if both are 'listen' then order based on refs
    if (a.type.method === "listen" && b.type.method === "listen") return a.reference.length - b.reference.length;
    // move `a` up since `a` is 'listen'
    if (a.type.method === "listen") return -1;
    // move `b` up since `b` is 'listen'
    if (b.type.method === "listen") return 1;

    // no change
    return 0;
});

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

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

Comments

1

const cards = [
  {
    type: { method: 'listen' },
    reference: ['destroyed', 'word 2']
  },
  {
    type: { method: 'synonym' },
    reference: ['destroyed']
  },
  {
    type: { method: 'listen' },
    reference: ['destroyed']
  },
  {
    type: { method: 'dictate' },
    reference: ['destroyed']
  }
]

const sortedCards = cards.sort((a, b) => {
  const priority = ['listen', 'synonym', 'dictate'];
  const indexA = priority.indexOf(a.type.method);
  const indexB = priority.indexOf(b.type.method);
  
  // First try to compare against the type
  // If the types are equal, it will be eval to 0 from (indexA - indexB).
  // 0 is considered false in javascript and hence will evulate the length of the reference.
  return indexA - indexB || a.reference.length - b.reference.length;
});

console.log(sortedCards);

Comments

0

When the sort() function compares two values, it sends the values to the compare function, and sorts the values according to the returned (negative, zero, positive) value.

If the result is negative, a is sorted before b.

If the result is positive, b is sorted before a.

If the result is 0, no changes are done with the sort order of the two values.

Example:

The compare function compares all the values in the array, two values at a time (a, b).

When comparing 40 and 100, the sort() method calls the compare function(40, 100).

The function calculates 40 - 100 (a - b), and since the result is negative (-60), the sort function will sort 40 as a value lower than 100.

You can use this code snippet to experiment with numerically and alphabetically sorting:

So based on that (even though its kinda ugly):

cards.sort(compare);
function compare(a, b) {
          if(b.type.method == "dictate") return -1000
          if(a.type.method == "listen" && b.type.method !== "listen") return -1.5
          if(a.type.method === "listen" && b.type.method === "listen") 
      return a.reference.length - b.reference.length
    }
const cards = [
      {
        type: { method: 'listen' },
        reference: ['destroyed', 'word 2']
      },
      {
        type: { method: 'synonym' },
        reference: ['destroyed']
      },
      {
        type: { method: 'listen' },
        reference: ['destroyed']
      },
      {
        type: { method: 'dictate' },
        reference: ['destroyed 1']
      },
      {
        type: { method: 'listen' },
        reference: ['destroyed', 'word 2', 'type 3']
      },
      {
        type: { method: 'synonym' },
        reference: ['destroyed']
      },
      {
        type: { method: 'listen' },
        reference: ['destroyed', 'listen']
      },
      {
        type: { method: 'dictate' },
        reference: ['destroyed']
      },
      {
        type: { method: 'listen' },
        reference: ['destroyed', 'listen']
      },
    ]

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.