JavaScriptの並べ替えを一度に解決する

前書き

多くの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
      
      



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





  • 私ができる最善のJavaScriptソリューションは、npmで利用できるbetter-cmpライブラリに組み込まれています








All Articles