List compare, diff or substraction?

I have an assertion in my nix config that checks no duplicates are in a list addresses.

      {
        assertion = builtins.length (lib.lists.unique addresses)
          == builtins.length addresses;
        message = ''
          Duplicate addresses found for the wireguard network:

          ${lib.strings.concatLines (builtins.sort (p: q: p < q) addresses)}'';
      }

This works fine and detects if there are duplicate addresses in the list. But I want to show the duplicate address in the message. Now, I just all the address sorted, but with lots of addresses it is not easy to find the duplicate(s). I’m looking for a function like this:

duplicates = lib.lists.compare addresses (lib.lists.unique addresses);

Then my assertion can just check if duplicates == [ ]; and show the duplicates in the message.

Any other ideas on how to accomplish the same are also welcome!

Not sure how I overlooked that :thinking: but it doesn’t do what I hoped for:

nix-repl> lib.lists.subtractLists [ 1 1 2 3 ] [ 1 2 3 ]
[ ]

nix-repl> lib.lists.subtractLists [ 1 2 3 ] [ 1 1 2 3 ]
[ ]

You’re right, after looking at the impl, that won’t help here. Found one possible solution:

nix-repl> with lib; filterAttrs (_: v: v > 1) (groupBy' (x: _: x+1) 0 toString [1 2 2 2 2 2 3])
{ "2" = 5; }

You could then use attrNames to just get the duplicate entries if you wish.

1 Like

I’ve created a function that does the trick:

let
  subtractLists = a: b: let
    foundIndex = lib.lists.findFirstIndex (x: x == lib.lists.head b) null a;
    length =  builtins.length a;
  in
    if a == [] then [] else
    if b == [] then a else
    if foundIndex == null then
      subtractLists a (lib.lists.tail b)
    else
      subtractLists (lib.lists.sublist 0 foundIndex a ++ lib.lists.sublist (foundIndex + 1) length a) (lib.lists.tail b);
in
  subtractLists [ 1 1 3 2 ] [ 1 2 3 ]
1 Like