lib.lists.commonPrefix: init
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
{ lib }:
|
{ lib }:
|
||||||
let
|
let
|
||||||
inherit (lib.strings) toInt;
|
inherit (lib.strings) toInt;
|
||||||
inherit (lib.trivial) compare min;
|
inherit (lib.trivial) compare min id;
|
||||||
inherit (lib.attrsets) mapAttrs;
|
inherit (lib.attrsets) mapAttrs;
|
||||||
in
|
in
|
||||||
rec {
|
rec {
|
||||||
@@ -663,6 +663,32 @@ rec {
|
|||||||
else if start + count > len then len - start
|
else if start + count > len then len - start
|
||||||
else count);
|
else count);
|
||||||
|
|
||||||
|
/* The common prefix of two lists.
|
||||||
|
|
||||||
|
Type: commonPrefix :: [a] -> [a] -> [a]
|
||||||
|
|
||||||
|
Example:
|
||||||
|
commonPrefix [ 1 2 3 4 5 6 ] [ 1 2 4 8 ]
|
||||||
|
=> [ 1 2 ]
|
||||||
|
commonPrefix [ 1 2 3 ] [ 1 2 3 4 5 ]
|
||||||
|
=> [ 1 2 3 ]
|
||||||
|
commonPrefix [ 1 2 3 ] [ 4 5 6 ]
|
||||||
|
=> [ ]
|
||||||
|
*/
|
||||||
|
commonPrefix =
|
||||||
|
list1:
|
||||||
|
list2:
|
||||||
|
let
|
||||||
|
# Zip the lists together into a list of booleans whether each element matches
|
||||||
|
matchings = zipListsWith (fst: snd: fst != snd) list1 list2;
|
||||||
|
# Find the first index where the elements don't match,
|
||||||
|
# which will then also be the length of the common prefix.
|
||||||
|
# If all elements match, we fall back to the length of the zipped list,
|
||||||
|
# which is the same as the length of the smaller list.
|
||||||
|
commonPrefixLength = findFirstIndex id (length matchings) matchings;
|
||||||
|
in
|
||||||
|
take commonPrefixLength list1;
|
||||||
|
|
||||||
/* Return the last element of a list.
|
/* Return the last element of a list.
|
||||||
|
|
||||||
This function throws an error if the list is empty.
|
This function throws an error if the list is empty.
|
||||||
|
|||||||
@@ -488,6 +488,39 @@ runTests {
|
|||||||
expected = { a = [ 2 3 ]; b = [7]; c = [8];};
|
expected = { a = [ 2 3 ]; b = [7]; c = [8];};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
testListCommonPrefixExample1 = {
|
||||||
|
expr = lists.commonPrefix [ 1 2 3 4 5 6 ] [ 1 2 4 8 ];
|
||||||
|
expected = [ 1 2 ];
|
||||||
|
};
|
||||||
|
testListCommonPrefixExample2 = {
|
||||||
|
expr = lists.commonPrefix [ 1 2 3 ] [ 1 2 3 4 5 ];
|
||||||
|
expected = [ 1 2 3 ];
|
||||||
|
};
|
||||||
|
testListCommonPrefixExample3 = {
|
||||||
|
expr = lists.commonPrefix [ 1 2 3 ] [ 4 5 6 ];
|
||||||
|
expected = [ ];
|
||||||
|
};
|
||||||
|
testListCommonPrefixEmpty = {
|
||||||
|
expr = lists.commonPrefix [ ] [ 1 2 3 ];
|
||||||
|
expected = [ ];
|
||||||
|
};
|
||||||
|
testListCommonPrefixSame = {
|
||||||
|
expr = lists.commonPrefix [ 1 2 3 ] [ 1 2 3 ];
|
||||||
|
expected = [ 1 2 3 ];
|
||||||
|
};
|
||||||
|
testListCommonPrefixLazy = {
|
||||||
|
expr = lists.commonPrefix [ 1 ] [ 1 (abort "lib.lists.commonPrefix shouldn't evaluate this")];
|
||||||
|
expected = [ 1 ];
|
||||||
|
};
|
||||||
|
# This would stack overflow if `commonPrefix` were implemented using recursion
|
||||||
|
testListCommonPrefixLong =
|
||||||
|
let
|
||||||
|
longList = genList (n: n) 100000;
|
||||||
|
in {
|
||||||
|
expr = lists.commonPrefix longList longList;
|
||||||
|
expected = longList;
|
||||||
|
};
|
||||||
|
|
||||||
testSort = {
|
testSort = {
|
||||||
expr = sort builtins.lessThan [ 40 2 30 42 ];
|
expr = sort builtins.lessThan [ 40 2 30 42 ];
|
||||||
expected = [2 30 40 42];
|
expected = [2 30 40 42];
|
||||||
|
|||||||
Reference in New Issue
Block a user