前書き
多くのJavaScript開発者は、クライアント側でデータを並べ替えた経験があります。残念ながら、既存のライブラリには小さな欠陥があります。しかし、これらの欠点が足し合わされ、プログラマーがソートについて考える方法が制限されます。これらの制限を克服するために、さまざまな言語での並べ替えを見てみましょう。この知識を身につければ、最も便利で厳密なインターフェースを選択できるようになります。
すべてが始まった経緯
ある晴れた夏の日、AngularJSを使用したプロジェクトで、テーブルに並べ替え関数を追加するタスクがありました。この場合、一度にソートするための複数の基準があり、各基準の方向は独立している可能性があります。
要件のリスト:
並べ替えのキーとして複数の式を使用する
キーごとに個別に並べ替えの方向を指定する機能
文字列を大文字と小文字を区別せず、ロケールを区別して並べ替える機能
-
AngularJSはソートのために何を提供しますか?フィルタ:orderByドキュメント
{{ orderBy_expression | orderBy : expression : reverse : comparator }}
$filter('orderBy')(collection, expression, reverse, comparator)
Example:
<tr ng-repeat="friend in friends | orderBy:'-age'">...</tr>
. , -
, , . , . , ? , , JS, . AngularJS, eval
, . AngularJS JS. , TypeScript . expression
, , . , . , .
, — reverse
. ! , . , .
— comparator
, . , comparator
. localeSensitiveComparator
.
, , TypeScript ? JavaScript , , -.
lodash
lodash
, _.sortBy
, .
var users = [
{ 'user': 'fred', 'age': 48 },
{ 'user': 'barney', 'age': 36 },
{ 'user': 'fred', 'age': 40 },
{ 'user': 'barney', 'age': 34 }
];
_.sortBy(users, [(o) => o.user]);
// => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
_.sortBy(users, ['user', 'age']);
// => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
, , ? - lodash
, _.orderBy
.
This method is like
_.sortBy
except that it allows specifying the sort orders of the iteratees to sort by.
, . :
// Sort by `user` in ascending order and by `age` in descending order.
_.orderBy(users, ['user', 'age'], ['asc', 'desc']);
// => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
— , . , , .
, _.orderBy
.
Array#sort
JavaScript, Array
sort
. . . , . , , — . . , .
items.sort(function(a, b) {
if (b.salary < a.salary) {
return -1;
}
if (b.salary > a.salary) {
return 1;
}
if (a.id < b.id) {
return -1;
}
if (a.id > b.id) {
return 1;
}
return 0;
});
// , `lodash`
// :
lodash.orderBy(items, ['salary', 'id'], ['desc', 'asc']);
, , . , .
, .
SQL / SEQUEL
, , . , , ! , SQL.
, SQL 1976 , . , , ?
SELECT EMPNO,NAME,SAL
FROM EMP
WHERE DNO 50
ORDER BY EMPNO
SQL , :
SELECT EMPNO,NAME,SAL
FROM EMP
ORDER BY SAL DESC, EMPNO ASC
Haskell Rust
Haskell Rust :
Haskell sortOn:
import Data.Ord (Down)
import Data.Sort (sortOn)
sortOn (\employee -> (Down (salary employee), employee_id employee)) employees
Rust slice::sort_by_key:
use std::cmp::{Reverse};
slice.sort_by_key(|employee| (Reverse(employee.salary), employee.id))
, — (newtype) Down Reverse, . , .
Python
Python list.sort sorted, key
.
sorted(employees, key=lambda employee: (employee.salary, employee.id))
Python, Haskell Rust, , . , , - . , , .
from ord_reverse import Reverse
sorted(employees, key=lambda employee: (Reverse(employee.salary), employee.id))
Java C#
Java Arrays.sort
Comparator
( ). Comparator
, , thenComparing
. reversed
.
Comparator<Employee> comparator = Comparator.comparing(Employee.getSalary).reversed() .thenComparing(Employee.getId); Arrays.sort(array, comparator);
— . ORDER BY SALARY ASC, ID DESC
:
// 1, ,
Comparator<Employee> comparator =
Comparator.comparing(Employee.getSalary)
.thenComparing(Comparator.comparing(Employee.getId).reversed());
// 2, .
// .
Comparator<Employee> comparator =
Comparator.comparing(Employee.getSalary).reversed()
.thenComparing(Employee.getId).reversed();
LINQ Query, SQL, C# Enumerable.OrderBy
Enumerable.OrderByDescending
, Enumerable.ThenBy
Enumerable.ThenByDescending
.
IEnumerable<Employee> query = employees .OrderByDescending(employee => employee.Salary) .ThenBy(employee => employee.Id);
Java . — , : IEnumerable
— 4 , 1 Haskell/Rust/Python. C# , .
, Java, C# . , .
C C++
C qsort:
#include <stdlib.h>
int cmp_employee(const void *p1, const void *p2)
{
const employee *a = (employee*)p1;
const employee *b = (employee*)p2;
if (b->salary < a->salary) {
return -1;
}
if (b->salary > a->salary) {
return 1;
}
if (a->id < b->id) {
return -1;
}
if (a->id > b->id) {
return 1;
}
return 0;
}
/* ... */
qsort(employees, count, sizeof(employee), cmp_employee);
C++ std::sort:
#include <algorithm>
/* ... */
std::sort(employees.begin(), employees.end(), [](const employee &a, const employee &b) {
if (b->salary < a->salary) {
return true;
}
if (b->salary > a->salary) {
return false;
}
return a->id < b->id;
});
C, C++ . C ( , ), C++ — . - , . , C++ .
C C++ . Array#sort
, , .
, Haskell Rust. JavaScript?
JS , , JS . , . ?
sortBy(array, (employee) => [{ reverse: employee.salary }, employee.id]);
JavaScript
, . JavaScript , , Trait
- typeclass
-, , .
:
null
.Maybe
Option
.
, .
NaN
.
, , BigInt JavaScript.
, .
{ reverse: xxx }
,xxx
.Down
/Reverse
{ localeCompare: sss, collator: ccc }
,sss
ccc
. .
.
- , . .
, — : better-cmp
: X?
orderBy: "Inspired by Angular's orderBy filter", . .
thenby: , Java , - .
multisort: ಠ_ಠ
if (/[^\(\r\n]*\([^\(\r\n]*\)$/.test(nextKey)) { var indexOfOpenParenthesis = nextKey.indexOf("("); var args = JSON.parse("[" + nextKey.slice(indexOfOpenParenthesis+1, -1) + "]"); nextKey = nextKey.slice(0, indexOfOpenParenthesis); }
, .
.
" " JavaScript .
私ができる最善のJavaScriptソリューションは、npmで利用できるbetter-cmpライブラリに組み込まれています。