JavaScript-Sortierung ein für alle Mal lösen

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





  • Sortierstabilität





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
      
      



. , SQL .





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



.





cmp, .





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



-, , .





:





  1. null



    . Maybe



    Option



    .





  2. , .





  3. NaN



    .





  4. , , BigInt JavaScript.





  5. , .





  6. { reverse: xxx }



    , xxx



    . Down



    / Reverse







  7. { localeCompare: sss, collator: ccc }



    , sss



    ccc



    . .





  8. .





- , . .





, — : 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.








All Articles