unique_prefixes.pl 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #!/usr/bin/perl
  2. # Author: Daniel "Trizen" Șuteu
  3. # License: GPLv3
  4. # Date: 28 September 2014
  5. # Website: https://github.com/trizen
  6. # Find the unique prefixes for an array of arrays of strings
  7. use 5.016;
  8. use strict;
  9. use warnings;
  10. sub abbrev {
  11. my ($array, $code) = @_;
  12. my $__END__ = {}; # some unique value
  13. my $__CALL__ = ref($code) eq 'CODE';
  14. my %table;
  15. foreach my $sub_array (@{$array}) {
  16. my $ref = \%table;
  17. foreach my $item (@{$sub_array}) {
  18. $ref = $ref->{$item} //= {};
  19. }
  20. $ref->{$__END__} = $sub_array;
  21. }
  22. my @abbrevs;
  23. sub {
  24. my ($hash) = @_;
  25. foreach my $key (my @keys = sort keys %{$hash}) {
  26. next if $key eq $__END__;
  27. __SUB__->($hash->{$key});
  28. if ($#keys > 0) {
  29. my $count = 0;
  30. my $ref = $hash->{$key};
  31. while (my ($key) = each %{$ref}) {
  32. if ($key eq $__END__) {
  33. my $arr = [@{$ref->{$key}}[0 .. $#{$ref->{$key}} - $count]];
  34. $__CALL__ ? $code->($arr) : push(@abbrevs, $arr);
  35. last;
  36. }
  37. $ref = $ref->{$key};
  38. $count++;
  39. }
  40. }
  41. }
  42. }
  43. ->(\%table);
  44. return \@abbrevs;
  45. }
  46. #
  47. ## Example: find the common directory from a list of dirs
  48. #
  49. my @dirs = qw(
  50. /home/user1/tmp/coverage/test
  51. /home/user1/tmp/covert/operator
  52. /home/user1/tmp/coven/members
  53. );
  54. require List::Util;
  55. my $unique_prefixes = abbrev([map { [split('/')] } @dirs]);
  56. my %table = map { $#{$_} => $_ } @{$unique_prefixes};
  57. my $min = List::Util::min(keys %table);
  58. say "=>> Common directory:";
  59. say join('/', splice(@{$table{$min}}, 0, -1));
  60. my @words = qw(
  61. deodorant
  62. decor
  63. decorat
  64. decadere
  65. plecare
  66. placere
  67. plecat
  68. jaguar
  69. );
  70. say "\n=>> Unique prefixes:";
  71. abbrev([map { [split //] } @words], sub { say @{$_[0]} });