Search code examples
javascriptarrayssortingmultidimensional-array

How do I sort arrays in an array by string using custom alphabet in JS?


Why this is not a duplicate: The "original" sorts by characters, not strings. I'm trying to sort by strings. This is a completely different question, it needs to be able to sort the entire string, not just one character.

I have this array:

[
    ["ik", "p", "I; me", 1],
    ["pat", "pre", "plus", 1],
    ["qeol", "adj", "only", 1],
    ["nei", "adj", "not", 1]
]

I want to sort the array alphabetically by the first item, and using a custom alphabet where q is between n and o instead.

So, it should look something like:

[
    ["ik", "p", "I; me", 1],
    ["nei", "adj", "not", 1],
    ["qeol", "adj", "only", 1],
    ["pat", "pre", "plus", 1]
]

I tried this and tried to tweak it so that the q to go between the n and o, but nothing worked.

words.sort(function(a, b) { 
    return a[0].toLowerCase() === "q" && a[0] < "n"? 1: (a[0] > b[0]? 1: -1);
});

I just tried random crap so of course nothing worked

How do I do this?


Solution

  • You could build a function for custom sorting by handing aover a string of characters an sort until the strings end.

    const 
        data = [["ik", "p", "I; me", 1], ["pat", "pre", "plus", 1], ["qeol", "adj", "only", 1], ["nei", "adj", "not", 1]],
        alphabet = ' abcdefghijklmnqoprstuvwxyz',
        sortBy = alphabet => {
            const order = Object.fromEntries([...alphabet].map((l, i) => [l, i + 1]));
        
            return (a, b) => {
                for (let i = 0, min = Math.min(a.length, b.length); i < min; i++) {
                    if (a[i] === b[i]) continue;
                    return order[a[i]] - order[b[i]];
                }
                return a.length - b.length;
            };
        },
        custom = (fn => (a, b) => fn(a[0], b[0]))(sortBy(alphabet));
    
    console.log(...["ikb", "nqq", "ik", "pat", "qeol", "nei", "npo", "nop", "ika"].sort(sortBy(alphabet)));
    
    console.log(data.sort(custom));
    .as-console-wrapper { max-height: 100% !important; top: 0; }