アルファベット順、大文字小文字無視したソート
次のようなコードがよく紹介されていました。
var source = ['a', 'B', 'A', 'b', 'aa', 'Aa', 'AA', 'aA', 'aB', 'ab', 'Ab', 'AB']
source.sort((a, b) => {
a = a.toLowerCase();
b = b.toLowerCase();
if (a < b) {
return -1;
} else if (a > b) {
return 1;
}
return 0;
})
console.log(source);
// [ 'a', 'A', 'AA', 'aA', 'aa', 'Aa', 'aB', 'ab', 'Ab', 'AB', 'B', 'b' ]
このコードだとある程度は文字列を並び替えられるのですが、大文字と小文字は同一視されているので、どちらかが優先されることがないです。
いわゆる辞書順を考えると、大文字を優先するか、小文字を優先するか、を判断したいところ。
アルファベット順、大文字、小文字、優先順位をつける。
次のようにします。
var source = ['a', 'B', 'A', 'b', 'aa', 'Aa', 'AA', 'aA', 'aB', 'ab', 'Ab', 'AB']
source.sort((a, b) => {
const la = a.toLowerCase();
const lb = b.toLowerCase();
if (la < lb) {
return -1;
} else if (la > lb) {
return 1;
} else {
for(let i = 0, l = a.length; i < l; i += 1) {
if (a[i] < b[i]) {
return -1;
}
if (b[i] < a[i]) {
return 1
}
}
}
})
console.log(source);
// [ 'A', 'a', 'AA', 'Aa', 'aA', 'aa', 'AB', 'Ab', 'aB', 'ab', 'B', 'b' ]
アルファベット順で、大小文字区別なしで同一文字の場合には、1文字ごとに並び順を判定するとよいです。
小文字優先にしたい場合は、for の内部の、-1 と 1 を入れ替えるとよいです。
// [ 'a', 'A', 'aa', 'aA', 'Aa', 'AA', 'ab', 'aB', 'Ab', 'AB', 'b', 'B' ]
追記:アルファベット順、大文字、小文字、優先順位をつける。
より効率よいコードを、コメント欄で @sugoroku_y さんに教えていただきました。ありがとうございます!
このように書いても同じ結果が出力されます。
var source = ['a', 'B', 'A', 'b', 'aa', 'Aa', 'AA', 'aA', 'aB', 'ab', 'Ab', 'AB']
source.sort((a, b) => {
const la = a.toLowerCase();
const lb = b.toLowerCase();
if (la < lb) {
return -1;
}
if (la > lb) {
return 1;
}
if (a < b) {
return -1;
}
if (b < a) {
return 1
}
})
console.log(source);
// ["A", "a", "AA", "Aa", "aA", "aa", "AB", "Ab", "aB", "ab", "B", "b"]
var source = ['a', 'B', 'A', 'b', 'aa', 'Aa', 'AA', 'aA', 'aB', 'ab', 'Ab', 'AB']
const sorted = source.map(
s => ({o: s, l: s.toLowerCase()})
).sort((a, b) => {
if (a.l < b.l) return -1;
if (a.l > b.l) return 1;
if (a.o < b.o) return -1;
if (a.o > b.o) return 1;
return 0;
}).map(e => e.o)
console.log(sorted)
// ["A", "a", "AA", "Aa", "aA", "aa", "AB", "Ab", "aB", "ab", "B", "b"]
JS Bin で動かせるコードを載せました。
https://jsbin.com/busucecotu/2/edit?html,js,console