Home > Net >  Alphanumeric and numeric strings sorting not working as expected
Alphanumeric and numeric strings sorting not working as expected

Time:02-03

I implemented below logic to apply sorting on mixed data(contains alphanumeric and numeric values) but it is not sorting as expected.

/*For numeric value sorting */
if (!isNaN(fVal) && !isNaN(lastVal)) {
    switch (policy) {
        case SORT_BY_DESC:
            return  fVal <  lastVal ? 1 : -1;
        case SORT_BY_ASC:
            return  fVal >  lastVal ? 1 : -1;
        default:
            return 0;
    }
} 
/* For alphanumeric sorting */
else {
    switch (policy) {
        case SORT_BY_DESC:
            return fVal < lastVal ? 1 : -1;
        case SORT_BY_ASC:
            return fVal > lastVal ? 1 : -1;
        default:
            return 0;
    }
}

If all the values are numeric this logic is working fine but if I have mixed data it is not sorting properly.

Raw Data - ['60091A0222', '633', '63372A1019', '63372A1021', '6667', '6789', '7776']

Expected Result -

Data in Descending order - 63372A1021, 63372A1019, 60091A0222, 7776, 6789, 633

Data in Ascending order - 633,, 6667, 6789, 7776, 60091A0222, 63372A1019, 63372A1021

What I am getting -

Descending order - 7776, 6789, 6667, 63372A1021, 63372A1019, 633, 60091A0222

Ascending order - 60091A0222, 633, 63372A1019, 63372A1021, 6667, 6789, 7776

CodePudding user response:

You could take a check for finiteness and sort this value to top.

const
    data = ['60091A0222', 633, '63372A1019', '63372A1021', 6667, 6789, 7776],
    asc = (a, b) => isFinite(b) - isFinite(a) || (a > b) - (a < b),
    desc = (a, b) => isFinite(a) - isFinite(b) || (a < b) - (a > b)

data.sort(asc);
console.log(...data);

data.sort(desc);
console.log(...data);

CodePudding user response:

You will need to split the strings into number/letter/number groups and sort based on the presence of each type of group.

const sortIndices = (data, desc = false) => {
  const pattern = /(?<=\d)(?=\D)|(?=\d)(?<=\D)/, dir = desc ? -1 : 1;
  return data.sort((a, b) => {
    const x = a.split(pattern), y = b.split(pattern);
    let diff;
    // Compare overall length
    if (a.length < b.length) return -1 * dir;
    if (b.length < a.length) return 1 * dir;
    // Find the difference between the first group (numeric)
    diff =  x[0] -  y[0];
    if (diff !== 0) return diff * dir;
    // If both contain at least two groups
    if (a.length < 2) return -1 * dir;
    if (b.length < 2) return 1 * dir;
    // Find the difference between the second group (alpha)
    diff = x[1].localeCompare(y[1]);
    if (diff !== 0) return diff * dir;
    // If both contain at least three groups
    if (a.length < 3) return -1 * dir;
    if (b.length < 3) return 1 * dir;
    // Find the difference between the third group (numeric)
    return ( x[2] -  y[2]) * dir;
  });
};

const data = ['7776', '6789', '6667', '63372A1021', '63372A1019', '633', '60091A0222'];

console.log(...sortIndices(data));       // Ascending
console.log(...sortIndices(data, true)); // Descending
.as-console-wrapper { top: 0; max-height: 100% !important; }

  • Related