X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=blobdiff_plain;f=src%2FPVE%2FTools.pm;h=676647eefb375d8d1ad00e9d06ab404baab9c906;hp=4dd073f8cf6a07b02055fc0bb6a97b9145b2b1db;hb=3982313e8d89982f109d4b4c6c1248d1b7d35512;hpb=0c078e6645ab644f979b367c1d8ee24f6e796822 diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm index 4dd073f..676647e 100644 --- a/src/PVE/Tools.pm +++ b/src/PVE/Tools.pm @@ -1649,4 +1649,43 @@ sub dev_t_minor($) { return (($dev_t >> 12) & 0xfff00) | ($dev_t & 0xff); } +# Given an array of array refs [ \[a b c], \[a b b], \[e b a] ] +# Returns the intersection of elements as a single array [a b] +sub array_intersect { + my ($arrays) = @_; + + if (!ref($arrays->[0])) { + $arrays = [ grep { ref($_) eq 'ARRAY' } @_ ]; + } + + return [] if scalar(@$arrays) == 0; + return $arrays->[0] if scalar(@$arrays) == 1; + + my $array_unique = sub { + my %seen = (); + return grep { ! $seen{ $_ }++ } @_; + }; + + # base idea is to get all unique members from the first array, then + # check the common elements with the next (uniquely made) one, only keep + # those. Repeat for every array and at the end we only have those left + # which exist in all arrays + my $return_arr = [ $array_unique->(@{$arrays->[0]}) ]; + for my $i (1 .. $#$arrays) { + my %count = (); + # $return_arr is already unique, explicit at before the loop, implicit below. + foreach my $element (@$return_arr, $array_unique->(@{$arrays->[$i]})) { + $count{$element}++; + } + $return_arr = []; + foreach my $element (keys %count) { + push @$return_arr, $element if $count{$element} > 1; + } + last if scalar(@$return_arr) == 0; # empty intersection, early exit + } + + return $return_arr; +} + + 1;