Use builtins.genList
This fixes the quadratic complexity of functions like imap.
This commit is contained in:
parent
273d9ffd6a
commit
5976d393fb
139
lib/lists.nix
139
lib/lists.nix
|
@ -4,7 +4,7 @@ with import ./trivial.nix;
|
||||||
|
|
||||||
rec {
|
rec {
|
||||||
|
|
||||||
inherit (builtins) head tail length isList elemAt concatLists filter elem;
|
inherit (builtins) head tail length isList elemAt concatLists filter elem genList;
|
||||||
|
|
||||||
|
|
||||||
# Create a list consisting of a single element. `singleton x' is
|
# Create a list consisting of a single element. `singleton x' is
|
||||||
|
@ -42,16 +42,20 @@ rec {
|
||||||
foldl' = builtins.foldl' or foldl;
|
foldl' = builtins.foldl' or foldl;
|
||||||
|
|
||||||
|
|
||||||
# map with index: `imap (i: v: "${v}-${toString i}") ["a" "b"] ==
|
# Map with index: `imap (i: v: "${v}-${toString i}") ["a" "b"] ==
|
||||||
# ["a-1" "b-2"]'
|
# ["a-1" "b-2"]'. FIXME: why does this start to count at 1?
|
||||||
imap = f: list:
|
imap =
|
||||||
let
|
if builtins ? genList then
|
||||||
len = length list;
|
f: list: genList (n: f (n + 1) (elemAt list n)) (length list)
|
||||||
imap' = n:
|
else
|
||||||
if n == len
|
f: list:
|
||||||
then []
|
let
|
||||||
else [ (f (n + 1) (elemAt list n)) ] ++ imap' (n + 1);
|
len = length list;
|
||||||
in imap' 0;
|
imap' = n:
|
||||||
|
if n == len
|
||||||
|
then []
|
||||||
|
else [ (f (n + 1) (elemAt list n)) ] ++ imap' (n + 1);
|
||||||
|
in imap' 0;
|
||||||
|
|
||||||
|
|
||||||
# Map and concatenate the result.
|
# Map and concatenate the result.
|
||||||
|
@ -120,10 +124,17 @@ rec {
|
||||||
|
|
||||||
|
|
||||||
# Return a list of integers from `first' up to and including `last'.
|
# Return a list of integers from `first' up to and including `last'.
|
||||||
range = first: last:
|
range =
|
||||||
if last < first
|
if builtins ? genList then
|
||||||
then []
|
first: last:
|
||||||
else [first] ++ range (first + 1) last;
|
if first > last
|
||||||
|
then []
|
||||||
|
else genList (n: first + n) (last - first + 1)
|
||||||
|
else
|
||||||
|
first: last:
|
||||||
|
if last < first
|
||||||
|
then []
|
||||||
|
else [first] ++ range (first + 1) last;
|
||||||
|
|
||||||
|
|
||||||
# Partition the elements of a list in two lists, `right' and
|
# Partition the elements of a list in two lists, `right' and
|
||||||
|
@ -136,23 +147,29 @@ rec {
|
||||||
) { right = []; wrong = []; };
|
) { right = []; wrong = []; };
|
||||||
|
|
||||||
|
|
||||||
zipListsWith = f: fst: snd:
|
zipListsWith =
|
||||||
let
|
if builtins ? genList then
|
||||||
len1 = length fst;
|
f: fst: snd: genList (n: f (elemAt fst n) (elemAt snd n)) (min (length fst) (length snd))
|
||||||
len2 = length snd;
|
else
|
||||||
len = if len1 < len2 then len1 else len2;
|
f: fst: snd:
|
||||||
zipListsWith' = n:
|
let
|
||||||
if n != len then
|
len = min (length fst) (length snd);
|
||||||
[ (f (elemAt fst n) (elemAt snd n)) ]
|
zipListsWith' = n:
|
||||||
++ zipListsWith' (n + 1)
|
if n != len then
|
||||||
else [];
|
[ (f (elemAt fst n) (elemAt snd n)) ]
|
||||||
in zipListsWith' 0;
|
++ zipListsWith' (n + 1)
|
||||||
|
else [];
|
||||||
|
in zipListsWith' 0;
|
||||||
|
|
||||||
zipLists = zipListsWith (fst: snd: { inherit fst snd; });
|
zipLists = zipListsWith (fst: snd: { inherit fst snd; });
|
||||||
|
|
||||||
|
|
||||||
# Reverse the order of the elements of a list. FIXME: O(n^2)!
|
# Reverse the order of the elements of a list.
|
||||||
reverseList = fold (e: acc: acc ++ [ e ]) [];
|
reverseList =
|
||||||
|
if builtins ? genList then
|
||||||
|
xs: let l = length xs; in genList (n: elemAt xs (l - n - 1)) l
|
||||||
|
else
|
||||||
|
fold (e: acc: acc ++ [ e ]) [];
|
||||||
|
|
||||||
|
|
||||||
# Sort a list based on a comparator function which compares two
|
# Sort a list based on a comparator function which compares two
|
||||||
|
@ -177,27 +194,46 @@ rec {
|
||||||
|
|
||||||
|
|
||||||
# Return the first (at most) N elements of a list.
|
# Return the first (at most) N elements of a list.
|
||||||
take = count: list:
|
take =
|
||||||
let
|
if builtins ? genList then
|
||||||
len = length list;
|
count: sublist 0 count
|
||||||
take' = n:
|
else
|
||||||
if n == len || n == count
|
count: list:
|
||||||
then []
|
let
|
||||||
else
|
len = length list;
|
||||||
[ (elemAt list n) ] ++ take' (n + 1);
|
take' = n:
|
||||||
in take' 0;
|
if n == len || n == count
|
||||||
|
then []
|
||||||
|
else
|
||||||
|
[ (elemAt list n) ] ++ take' (n + 1);
|
||||||
|
in take' 0;
|
||||||
|
|
||||||
|
|
||||||
# Remove the first (at most) N elements of a list.
|
# Remove the first (at most) N elements of a list.
|
||||||
drop = count: list:
|
drop =
|
||||||
let
|
if builtins ? genList then
|
||||||
len = length list;
|
count: list: sublist count (length list) list
|
||||||
drop' = n:
|
else
|
||||||
if n == -1 || n < count
|
count: list:
|
||||||
then []
|
let
|
||||||
else
|
len = length list;
|
||||||
drop' (n - 1) ++ [ (elemAt list n) ];
|
drop' = n:
|
||||||
in drop' (len - 1);
|
if n == -1 || n < count
|
||||||
|
then []
|
||||||
|
else
|
||||||
|
drop' (n - 1) ++ [ (elemAt list n) ];
|
||||||
|
in drop' (len - 1);
|
||||||
|
|
||||||
|
|
||||||
|
# Return a list consisting of at most ‘count’ elements of ‘list’,
|
||||||
|
# starting at index ‘start’.
|
||||||
|
sublist = start: count: list:
|
||||||
|
let len = length list; in
|
||||||
|
genList
|
||||||
|
(n: elemAt list (n + start))
|
||||||
|
(if start >= len then 0
|
||||||
|
else if start + count > len then len - start
|
||||||
|
else count);
|
||||||
|
|
||||||
|
|
||||||
# Return the last element of a list.
|
# Return the last element of a list.
|
||||||
|
@ -211,9 +247,11 @@ rec {
|
||||||
|
|
||||||
deepSeqList = xs: y: if any (x: deepSeq x false) xs then y else y;
|
deepSeqList = xs: y: if any (x: deepSeq x false) xs then y else y;
|
||||||
|
|
||||||
|
|
||||||
crossLists = f: foldl (fs: args: concatMap (f: map f args) fs) [f];
|
crossLists = f: foldl (fs: args: concatMap (f: map f args) fs) [f];
|
||||||
|
|
||||||
# Remove duplicate elements from the list
|
|
||||||
|
# Remove duplicate elements from the list. O(n^2) complexity.
|
||||||
unique = list:
|
unique = list:
|
||||||
if list == [] then
|
if list == [] then
|
||||||
[]
|
[]
|
||||||
|
@ -223,9 +261,12 @@ rec {
|
||||||
xs = unique (drop 1 list);
|
xs = unique (drop 1 list);
|
||||||
in [x] ++ remove x xs;
|
in [x] ++ remove x xs;
|
||||||
|
|
||||||
# Intersects list 'e' and another list
|
|
||||||
|
# Intersects list 'e' and another list. O(nm) complexity.
|
||||||
intersectLists = e: filter (x: elem x e);
|
intersectLists = e: filter (x: elem x e);
|
||||||
|
|
||||||
# Subtracts list 'e' from another list
|
|
||||||
|
# Subtracts list 'e' from another list. O(nm) complexity.
|
||||||
subtractLists = e: filter (x: !(elem x e));
|
subtractLists = e: filter (x: !(elem x e));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue