mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-26 08:53:21 +00:00
Merge pull request #272744 from hercules-ci/lib-lists-sortOn
`lib.lists.sortOn`: init
This commit is contained in:
commit
bf67c02b1b
@ -5,7 +5,7 @@ let
|
||||
intersectAttrs;
|
||||
inherit (lib)
|
||||
functionArgs isFunction mirrorFunctionArgs isAttrs setFunctionArgs
|
||||
optionalAttrs attrNames filter elemAt concatStringsSep sort take length
|
||||
optionalAttrs attrNames filter elemAt concatStringsSep sortOn take length
|
||||
filterAttrs optionalString flip pathIsDirectory head pipe isDerivation listToAttrs
|
||||
mapAttrs seq flatten deepSeq warnIf isInOldestRelease extends
|
||||
;
|
||||
@ -174,7 +174,7 @@ rec {
|
||||
# levenshteinAtMost is only fast for 2 or less.
|
||||
(filter (levenshteinAtMost 2 arg))
|
||||
# Put strings with shorter distance first
|
||||
(sort (x: y: levenshtein x arg < levenshtein y arg))
|
||||
(sortOn (levenshtein arg))
|
||||
# Only take the first couple results
|
||||
(take 3)
|
||||
# Quote all entries
|
||||
|
@ -91,7 +91,7 @@ let
|
||||
inherit (self.lists) singleton forEach foldr fold foldl foldl' imap0 imap1
|
||||
concatMap flatten remove findSingle findFirst any all count
|
||||
optional optionals toList range replicate partition zipListsWith zipLists
|
||||
reverseList listDfs toposort sort naturalSort compareLists take
|
||||
reverseList listDfs toposort sort sortOn naturalSort compareLists take
|
||||
drop sublist last init crossLists unique allUnique intersectLists
|
||||
subtractLists mutuallyExclusive groupBy groupBy';
|
||||
inherit (self.strings) concatStrings concatMapStrings concatImapStrings
|
||||
|
@ -4,6 +4,7 @@ let
|
||||
inherit (lib.strings) toInt;
|
||||
inherit (lib.trivial) compare min id;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
inherit (lib.lists) sort;
|
||||
in
|
||||
rec {
|
||||
|
||||
@ -591,9 +592,15 @@ rec {
|
||||
the second argument. The returned list is sorted in an increasing
|
||||
order. The implementation does a quick-sort.
|
||||
|
||||
See also [`sortOn`](#function-library-lib.lists.sortOn), which applies the
|
||||
default comparison on a function-derived property, and may be more efficient.
|
||||
|
||||
Example:
|
||||
sort (a: b: a < b) [ 5 3 7 ]
|
||||
sort (p: q: p < q) [ 5 3 7 ]
|
||||
=> [ 3 5 7 ]
|
||||
|
||||
Type:
|
||||
sort :: (a -> a -> Bool) -> [a] -> [a]
|
||||
*/
|
||||
sort = builtins.sort or (
|
||||
strictLess: list:
|
||||
@ -612,6 +619,42 @@ rec {
|
||||
if len < 2 then list
|
||||
else (sort strictLess pivot.left) ++ [ first ] ++ (sort strictLess pivot.right));
|
||||
|
||||
/*
|
||||
Sort a list based on the default comparison of a derived property `b`.
|
||||
|
||||
The items are returned in `b`-increasing order.
|
||||
|
||||
**Performance**:
|
||||
|
||||
The passed function `f` is only evaluated once per item,
|
||||
unlike an unprepared [`sort`](#function-library-lib.lists.sort) using
|
||||
`f p < f q`.
|
||||
|
||||
**Laws**:
|
||||
```nix
|
||||
sortOn f == sort (p: q: f p < f q)
|
||||
```
|
||||
|
||||
Example:
|
||||
sortOn stringLength [ "aa" "b" "cccc" ]
|
||||
=> [ "b" "aa" "cccc" ]
|
||||
|
||||
Type:
|
||||
sortOn :: (a -> b) -> [a] -> [a], for comparable b
|
||||
*/
|
||||
sortOn = f: list:
|
||||
let
|
||||
# Heterogenous list as pair may be ugly, but requires minimal allocations.
|
||||
pairs = map (x: [(f x) x]) list;
|
||||
in
|
||||
map
|
||||
(x: builtins.elemAt x 1)
|
||||
(sort
|
||||
# Compare the first element of the pairs
|
||||
# Do not factor out the `<`, to avoid calls in hot code; duplicate instead.
|
||||
(a: b: head a < head b)
|
||||
pairs);
|
||||
|
||||
/* Compare two lists element-by-element.
|
||||
|
||||
Example:
|
||||
|
@ -650,6 +650,28 @@ runTests {
|
||||
expected = [2 30 40 42];
|
||||
};
|
||||
|
||||
testSortOn = {
|
||||
expr = sortOn stringLength [ "aa" "b" "cccc" ];
|
||||
expected = [ "b" "aa" "cccc" ];
|
||||
};
|
||||
|
||||
testSortOnEmpty = {
|
||||
expr = sortOn (throw "nope") [ ];
|
||||
expected = [ ];
|
||||
};
|
||||
|
||||
testSortOnIncomparable = {
|
||||
expr =
|
||||
map
|
||||
(x: x.f x.ok)
|
||||
(sortOn (x: x.ok) [
|
||||
{ ok = 1; f = x: x; }
|
||||
{ ok = 3; f = x: x + 3; }
|
||||
{ ok = 2; f = x: x; }
|
||||
]);
|
||||
expected = [ 1 2 6 ];
|
||||
};
|
||||
|
||||
testReplicate = {
|
||||
expr = replicate 3 "a";
|
||||
expected = ["a" "a" "a"];
|
||||
|
@ -13,7 +13,7 @@ let
|
||||
mkIf
|
||||
mkOption
|
||||
optionalString
|
||||
sort
|
||||
sortOn
|
||||
types
|
||||
;
|
||||
|
||||
@ -37,7 +37,7 @@ let
|
||||
genConfig = set:
|
||||
let
|
||||
pairs = mapAttrsToList (name: value: { inherit name value; }) set;
|
||||
sortedPairs = sort (a: b: prioOf a < prioOf b) pairs;
|
||||
sortedPairs = sortOn prioOf pairs;
|
||||
in
|
||||
concatMap genPair sortedPairs;
|
||||
genSection = sec: secName: value:
|
||||
|
Loading…
Reference in New Issue
Block a user