Memecahkan penyortiran JavaScript sekali dan untuk selamanya

pengantar

Banyak pengembang JavaScript memiliki pengalaman menyortir data di sisi klien. Sayangnya, perpustakaan yang ada memiliki kekurangan kecil. Tetapi kekurangan ini menambah dan membatasi cara pemrogram berpikir tentang pengurutan. Untuk mengatasi keterbatasan ini, mari kita lihat pengurutan dalam berbagai bahasa. Berbekal pengetahuan ini, kita akan dapat memilih antarmuka yang paling nyaman dan ketat.





Bagaimana semuanya dimulai

Suatu hari musim panas yang cerah, pada sebuah proyek dengan AngularJS, saya ditugasi menambahkan fungsi sortir ke tabel. Dalam hal ini, mungkin ada beberapa kriteria untuk pengurutan sekaligus, dan arah untuk setiap kriteria bisa independen.





Daftar persyaratan:





  • gunakan banyak ekspresi sebagai kunci untuk menyortir





  • kemampuan untuk menentukan arah pengurutan secara independen untuk masing-masing tombol





  • kemampuan untuk menyortir string case insensitive dan locale sensitive





  • stabilitas penyortiran





Apa yang AngularJS tawarkan untuk kami sortir? filter: dokumentasi 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
      
      



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





  • Solusi JavaScript terbaik yang dapat saya lakukan sekarang diwujudkan dalam pustaka cmp yang lebih baik yang tersedia di npm.








All Articles