Einführung
Viele JavaScript-Entwickler haben die Erfahrung gemacht, Daten auf der Clientseite zu sortieren. Leider weisen die vorhandenen Bibliotheken kleinere Mängel auf. Diese Mängel summieren sich jedoch und schränken die Art und Weise ein, wie Programmierer über das Sortieren denken. Um diese Einschränkungen zu überwinden, betrachten wir das Sortieren in verschiedenen Sprachen. Mit diesem Wissen können wir die bequemste und strengste Benutzeroberfläche auswählen.
Wie alles begann
An einem schönen Sommertag wurde ich bei einem Projekt mit AngularJS beauftragt, einer Tabelle eine Sortierfunktion hinzuzufügen. In diesem Fall kann es mehrere Kriterien zum gleichzeitigen Sortieren geben, und die Richtung für jedes Kriterium kann unabhängig sein.
Liste der Anforderungen:
Verwenden Sie mehrere Ausdrücke als Schlüssel zum Sortieren
die Möglichkeit, die Sortierrichtung unabhängig für jeden der Schlüssel anzugeben
Die Möglichkeit, Zeichenfolgen ohne Berücksichtigung der Groß- und Kleinschreibung und ohne Berücksichtigung des Gebietsschemas zu sortieren
-
Was bietet uns AngularJS zum Sortieren? Filter: orderBy Dokumentation
{{ 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 .
Die beste JavaScript-Lösung, die ich machen konnte, ist jetzt in der besser-cmp- Bibliothek enthalten, die auf npm verfügbar ist.