1

This is an example of my array :

[
 1: { name: 'blablabla', difficulty: 'A2' },
 2: { name: 'bla', difficulty: 'A1' },
 3: { name: 'blablablabla', difficulty: 'B1' },
 4: { name: 'blablablabla', difficulty: 'B2' },
 5: { name: 'blablablabla', difficulty: 'A2' }
]

my_level: 'B2'

I want to sort the array so that my level of difficulty is the first item, i tried to use sort() but it's only to sort by 'ASC' or 'DESC', anyone have an idea of how to do it ? Thanks !

Tony S
  • 491
  • 6
  • 26

3 Answers3

4

You could sort by checking the value of difficulty with the wanted difficulty.

This approach moves the wanted value to top of the array.

const
    array = [{ name: 'blablabla', difficulty: 'A2' }, { name: 'bla', difficulty: 'A1' }, { name: 'blablablabla', difficulty: 'B1' }, { name: 'blablablabla', difficulty: 'B2' }, { name: 'blablablabla', difficulty: 'A2' }]
    difficulty = 'B2';

array.sort((a, b) => (b.difficulty === difficulty) - (a.difficulty === difficulty));

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
3

There's no need to sort it:

arr = [
 { name: 'blablabla', difficulty: 'A2' },
 { name: 'bla', difficulty: 'A1' },
 { name: 'blablablabla', difficulty: 'B1' },
 { name: 'blablablabla', difficulty: 'B2' },
 { name: 'blablablabla', difficulty: 'A2' },
 { name: 'one more', difficulty: 'B2' },
]

my_level = 'B2'

newArr = [
    ...arr.filter(x => x.difficulty === my_level),
    ...arr.filter(x => x.difficulty !== my_level),
    ]

console.log(newArr)

Advantages: 1) faster (I guess), 2) doesn't change the order, 3) doesn't break the original array

Here's some generic (and even faster) code:

// split array into two parts:
// part 0 - where predicate is false
// part 1 - where predicate is true

function partition(ary, predicate) {
    let parts = [[], []];
    for (let x of arr)
        parts[predicate(x) ? 1 : 0].push(x);
    return parts;
}

//

newArr = [].concat(...partition(arr, x => x.difficulty !== my_level))
georg
  • 211,518
  • 52
  • 313
  • 390
  • Heh, I had [a similar idea](https://jsbin.com/yecinid/1/edit?js,console) but `.slice()`-ing around the item index. Which would have added an `undefined` if the item wasn't found so, `.filter()` is probably the more robust approach for an immutable shifting of an item to the front. – VLAZ Apr 14 '21 at 08:57
  • 1
    @VLAZ: yep, if there's only one of them, we could just `splice` it out... But I hate splices ;) – georg Apr 14 '21 at 08:59
2

Provide a compare function to sort that takes in two parameters lets say a and b, and returns a value based on the following table.

a.difficulty === desired b.difficulty === desired Value returned by compare
true true 0
true false -1
false true 1
false false 0

const 
  data = [
    { name: "blablabla", difficulty: "A2" },
    { name: "bla", difficulty: "A1" },
    { name: "blablablabla", difficulty: "B1" },
    { name: "blablablabla", difficulty: "B2" },
    { name: "blablablabla", difficulty: "A2" },
  ],
  desired = "B2",
  table = { true: { true: 0, false: -1 }, false: { true: 1, false: 0 } },
  sortedData = [...data].sort(
    (a, b) => table[a.difficulty === desired][b.difficulty === desired]
  );

console.log(sortedData);
Som Shekhar Mukherjee
  • 4,701
  • 1
  • 12
  • 28
  • Just a tip - if you don't like nested conditional statements (like me...) you can encode the results into a table and just lookup based on a boolean: [demo](https://jsbin.com/puzorap/1/edit?js,console). Although, honestly, it's still a bit ugly. Whitespace formatting only helps so much. However, it might be useful if the nested conditionals are more complex and you start having even more branches. – VLAZ Apr 14 '21 at 09:19