■ はじめに
https://dk521123.hatenablog.com/entry/2021/02/10/225119
の続き。 ソートに関して、記事が長くなったので、分冊。 結構、落とし穴もあるので、その辺も追記。
目次
例1:クラスのソート 例2:同一の値が存在する場合の対応 ■ 使用上の注意:大文字・小文字に関して 対応策1)toLowerCase()で小文字(もしくは大文字)に統一してからソート 対応策2)localeCompare() を使ってソート
例1:クラスのソート
function sortList( targetList: any[], sortType: string, sortItem: string ) { targetList.sort((source, target) => { if (sortType === 'ASC') { // 昇順 if (source[sortItem] < target[sortItem]) { return -1; } if (source[sortItem] > target[sortItem]) { return 1; } } else { // 降順 if (source[sortItem] > target[sortItem]) { return -1; } if (source[sortItem] < target[sortItem]) { return 1; } } return 0; }); } const people = [ {id: 1, name: 'Mike', birthDate: '1922-02-20'}, {id: 5, name: 'Sam', birthDate: '2011-12-09'}, {id: 2, name: 'Kevin', birthDate: '1983-07-10'}, {id: 3, name: 'Tom', birthDate: '1978-01-04'}, {id: 4, name: 'Alex', birthDate: '2012-11-23'}, ]; console.log('* id ******************'); sortList(people, 'ASC', 'id'); console.log(people); console.log('*******************'); sortList(people, 'DESC', 'id'); console.log(people); console.log('* name ******************'); sortList(people, 'ASC', 'name'); console.log(people); console.log('*******************'); sortList(people, 'DESC', 'name'); console.log(people); console.log('* birthDate ******************'); sortList(people, 'ASC', 'birthDate'); console.log(people); console.log('*******************'); sortList(people, 'DESC', 'birthDate'); console.log(people); console.log('*******************'); console.log('Done');
出力結果
* id ****************** [ { id: 1, name: 'Mike', birthDate: '1922-02-20' }, { id: 2, name: 'Kevin', birthDate: '1983-07-10' }, { id: 3, name: 'Tom', birthDate: '1978-01-04' }, { id: 4, name: 'Alex', birthDate: '2012-11-23' }, { id: 5, name: 'Sam', birthDate: '2011-12-09' } ] ******************* [ { id: 5, name: 'Sam', birthDate: '2011-12-09' }, { id: 4, name: 'Alex', birthDate: '2012-11-23' }, { id: 3, name: 'Tom', birthDate: '1978-01-04' }, { id: 2, name: 'Kevin', birthDate: '1983-07-10' }, { id: 1, name: 'Mike', birthDate: '1922-02-20' } ] * name ****************** [ { id: 4, name: 'Alex', birthDate: '2012-11-23' }, { id: 2, name: 'Kevin', birthDate: '1983-07-10' }, { id: 1, name: 'Mike', birthDate: '1922-02-20' }, { id: 5, name: 'Sam', birthDate: '2011-12-09' }, { id: 3, name: 'Tom', birthDate: '1978-01-04' } ] ******************* [ { id: 3, name: 'Tom', birthDate: '1978-01-04' }, { id: 5, name: 'Sam', birthDate: '2011-12-09' }, { id: 1, name: 'Mike', birthDate: '1922-02-20' }, { id: 2, name: 'Kevin', birthDate: '1983-07-10' }, { id: 4, name: 'Alex', birthDate: '2012-11-23' } ] * birthDate ****************** [ { id: 1, name: 'Mike', birthDate: '1922-02-20' }, { id: 3, name: 'Tom', birthDate: '1978-01-04' }, { id: 2, name: 'Kevin', birthDate: '1983-07-10' }, { id: 5, name: 'Sam', birthDate: '2011-12-09' }, { id: 4, name: 'Alex', birthDate: '2012-11-23' } ] ******************* [ { id: 4, name: 'Alex', birthDate: '2012-11-23' }, { id: 5, name: 'Sam', birthDate: '2011-12-09' }, { id: 2, name: 'Kevin', birthDate: '1983-07-10' }, { id: 3, name: 'Tom', birthDate: '1978-01-04' }, { id: 1, name: 'Mike', birthDate: '1922-02-20' } ] ******************* Done
例2:同一の値が存在する場合の対応
function compare(sortKey: string, sortType: string, source: any, target: any) { // console.debug(`sortKey = ${sortKey}, sortType = ${sortType}`); // console.debug(`source = ${source[sortKey]}, target = ${target[sortKey]}`); let result = 0; if (sortType === 'ASC') { // Ascending if (source[sortKey] < target[sortKey]) { result = -1; } if (source[sortKey] > target[sortKey]) { result = 1; } } else { // Descending if (source[sortKey] > target[sortKey]) { result = -1; } if (source[sortKey] < target[sortKey]) { result = 1; } } // console.debug(`result = ${result}`); return result; } function sortList( targetList: any[], sortType: string, ) { targetList.sort((source, target) => { let result = compare('birthDate', sortType, source, target); if (result === 0) { result = compare('name', sortType, source, target); if (result === 0) { result = compare('id', sortType, source, target); } } return result }); } const people = [ {id: 7, name: 'Mike', birthDate: '1922-02-20'}, {id: 5, name: 'Sam', birthDate: '2011-12-09'}, {id: 2, name: 'Kevin', birthDate: '1983-07-10'}, {id: 3, name: 'Tom', birthDate: '1978-01-04'}, {id: 9, name: 'Tom', birthDate: '2011-12-09'}, {id: 8, name: 'Sam', birthDate: '2011-12-09'}, {id: 10, name: 'Kevin', birthDate: '2011-12-09'}, {id: 1, name: 'Mike', birthDate: '1922-02-20'}, {id: 4, name: 'Alex', birthDate: '2012-11-23'}, {id: 6, name: 'Mike', birthDate: '1922-02-20'}, ]; console.log('* ASC(昇順) birthDate->name->id ******'); sortList(people, 'ASC'); console.log(people); console.log('*******************'); console.log('* DESC(降順) birthDate->name->id *****'); sortList(people, 'DESC'); console.log(people); console.log('*******************'); console.log('Done');
出力結果
* ASC(昇順) birthDate->name->id ****** [ { id: 1, name: 'Mike', birthDate: '1922-02-20' }, { id: 6, name: 'Mike', birthDate: '1922-02-20' }, { id: 7, name: 'Mike', birthDate: '1922-02-20' }, { id: 3, name: 'Tom', birthDate: '1978-01-04' }, { id: 2, name: 'Kevin', birthDate: '1983-07-10' }, { id: 10, name: 'Kevin', birthDate: '2011-12-09' }, { id: 5, name: 'Sam', birthDate: '2011-12-09' }, { id: 8, name: 'Sam', birthDate: '2011-12-09' }, { id: 9, name: 'Tom', birthDate: '2011-12-09' }, { id: 4, name: 'Alex', birthDate: '2012-11-23' } ] ******************* * DESC(降順) birthDate->name->id ***** [ { id: 4, name: 'Alex', birthDate: '2012-11-23' }, { id: 9, name: 'Tom', birthDate: '2011-12-09' }, { id: 8, name: 'Sam', birthDate: '2011-12-09' }, { id: 5, name: 'Sam', birthDate: '2011-12-09' }, { id: 10, name: 'Kevin', birthDate: '2011-12-09' }, { id: 2, name: 'Kevin', birthDate: '1983-07-10' }, { id: 3, name: 'Tom', birthDate: '1978-01-04' }, { id: 7, name: 'Mike', birthDate: '1922-02-20' }, { id: 6, name: 'Mike', birthDate: '1922-02-20' }, { id: 1, name: 'Mike', birthDate: '1922-02-20' } ] ******************* Done
■ 使用上の注意:大文字・小文字に関して
大文字・小文字が混じっている場合、例1をそのまま使うと 以下「考慮がされていない場合」のようになる。 => 昇順の場合、大文字⇒小文字でソートされている
対応案
https://stackoverflow.com/questions/8996963/how-to-perform-case-insensitive-sorting-in-javascript
に記載されている方法は、 1)toLowerCase()で小文字(もしくは大文字)に統一してからソート 2)localeCompare() を使ってソート
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
考慮がされていない場合
// 例1を一部修正 const people = [ {id: 1, name: 'Mike', birthDate: '1922-02-20'}, {id: 5, name: 'mike', birthDate: '2011-12-09'}, {id: 2, name: 'alex', birthDate: '1983-07-10'}, {id: 3, name: 'Tom', birthDate: '1978-01-04'}, {id: 4, name: 'Alex', birthDate: '2012-11-23'}, ]; console.log('* name ******************'); sortList(people, 'ASC', 'name'); console.log(people); console.log('*******************'); sortList(people, 'DESC', 'name'); console.log(people); console.log('Done');
出力結果
* name ****************** [ { id: 4, name: 'Alex', birthDate: '2012-11-23' }, { id: 1, name: 'Mike', birthDate: '1922-02-20' }, { id: 3, name: 'Tom', birthDate: '1978-01-04' }, { id: 2, name: 'alex', birthDate: '1983-07-10' }, { id: 5, name: 'mike', birthDate: '2011-12-09' } ] ******************* [ { id: 5, name: 'mike', birthDate: '2011-12-09' }, { id: 2, name: 'alex', birthDate: '1983-07-10' }, { id: 3, name: 'Tom', birthDate: '1978-01-04' }, { id: 1, name: 'Mike', birthDate: '1922-02-20' }, { id: 4, name: 'Alex', birthDate: '2012-11-23' } ] Done
1)toLowerCase()で小文字(もしくは大文字)に統一してからソート
function sortList( targetList: any[], sortType: string, sortItem: string ) { targetList.sort((source, target) => { // 小文字で統一する const sourceValue = source[sortItem].toLowerCase(); const targetValue = target[sortItem].toLowerCase(); if (sortType === 'ASC') { // 昇順 if (sourceValue < targetValue) { return -1; } if (sourceValue > targetValue) { return 1; } } else { // 降順 if (sourceValue > targetValue) { return -1; } if (sourceValue < targetValue) { return 1; } } return 0; }); } // ... 略 ...
出力結果
* name ****************** [ { id: 2, name: 'alex', birthDate: '1983-07-10' }, { id: 4, name: 'Alex', birthDate: '2012-11-23' }, { id: 1, name: 'Mike', birthDate: '1922-02-20' }, { id: 5, name: 'mike', birthDate: '2011-12-09' }, { id: 3, name: 'Tom', birthDate: '1978-01-04' } ] ******************* [ { id: 3, name: 'Tom', birthDate: '1978-01-04' }, { id: 1, name: 'Mike', birthDate: '1922-02-20' }, { id: 5, name: 'mike', birthDate: '2011-12-09' }, { id: 2, name: 'alex', birthDate: '1983-07-10' }, { id: 4, name: 'Alex', birthDate: '2012-11-23' } ] Done
2)localeCompare() を使ってソート
function sortList( targetList: any[], sortType: string, sortItem: string ) { targetList.sort((source, target) => { const sourceValue = source[sortItem]; const targetValue = target[sortItem]; let result = sourceValue.localeCompare(targetValue, undefined, { sensitivity: 'base' }) if (sortType === 'ASC') { // 昇順 return result; } else { return result * (-1); } }); } // ... 略 ...
出力結果
* name ****************** [ { id: 2, name: 'alex', birthDate: '1983-07-10' }, { id: 4, name: 'Alex', birthDate: '2012-11-23' }, { id: 1, name: 'Mike', birthDate: '1922-02-20' }, { id: 5, name: 'mike', birthDate: '2011-12-09' }, { id: 3, name: 'Tom', birthDate: '1978-01-04' } ] ******************* [ { id: 3, name: 'Tom', birthDate: '1978-01-04' }, { id: 1, name: 'Mike', birthDate: '1922-02-20' }, { id: 5, name: 'mike', birthDate: '2011-12-09' }, { id: 2, name: 'alex', birthDate: '1983-07-10' }, { id: 4, name: 'Alex', birthDate: '2012-11-23' } ]
関連記事
TypeScript ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/12/21/180904
ループ操作 ~ map etc ~
https://dk521123.hatenablog.com/entry/2021/01/03/000000
配列・リスト操作
https://dk521123.hatenablog.com/entry/2021/02/10/225119
配列・リスト操作 ~ スプレッド構文 / Three-dots ~
https://dk521123.hatenablog.com/entry/2021/03/09/000000