in reply to Re^4: Advanced Bubble Sort
in thread Advanced Bubble Sort

Ok, fair enough.

If it can be determined exactly what the "version" string is, then I perhaps would use an algorithm like below. One pass through the data, no sorting. Use a hash table with a key of the "generic name" and value of the version. If the version is greater, then replace the hash value with the greater version.

Of course this can become very complex in the real world because version naming conventions vary widely.

However, I think this was a successful thread in that the main issues have been discussed and some techniques demo'd. I did this quickly and perhaps there are some minor point to quibble about. But I think the general idea of this approach is solid.

#!/usr/bin/perl use warnings; use strict; my %versions; while (my $line = <DATA>) { next if $line =~ /^\s*$/; #skip blank lines $line =~ s/\s*$//; my ($name, $version, $platform) = $line =~ /^([a-zA-Z-]+)-([\d\._-]+)\.(.*)$/; # set a default value if needed. $versions{"$name:$platform"} //= "0.0.0-0"; if (cmp_verA2B ($versions{"$name:$platform"}, $version)<0) { $versions{"$name:$platform"} = $version; } } foreach my $version (sort keys %versions) #print results { my $max_ver = $versions{$version}; my ($prefix,$suffix) =split ':', $version; print "$prefix\-$max_ver\.$suffix\n"; } sub cmp_verA2B { my ($verA, $verB) = @_; my ($majorA,$minorA,$subVerA) = split /\./,$verA; my ($majorB,$minorB,$subVerB) = split /\./,$verB; my ($subVerA1, $subVerA2) = split ('-',$subVerA); my ($subVerB1, $subVerB2) = split ('-',$subVerB); $majorA <=> $majorB or $minorA <=> $minorB or $subVerA1 <=> $subVerB1 or $subVerA2 <=> $subVerB2 } =Prints: abc-4.2.11-8.el7_2.x86_64 samba-common-libs-4.2.12-7.el7_2.x86_64 xyz-libs-4.2.13-7.el7_2.x86_64 =cut __DATA__ samba-common-libs-4.2.12-7.el7_2.x86_64 samba-common-libs-4.2.10-3.el7_2.x86_64 xyz-libs-4.2.10-7.el7_2.x86_64 samba-common-libs-4.2.10-6.el7_2.x86_64 abc-4.2.11-7.el7_2.x86_64 xyz-libs-4.2.11-7.el7_2.x86_64 abc-4.2.11-8.el7_2.x86_64 samba-common-libs-4.2.10-6.2.el7_2.x86_64 xyz-libs-4.2.12-7.el7_2.x86_64 xyz-libs-4.2.13-7.el7_2.x86_64 samba-common-libs-4.2.10-8.el7_2.x86_64

Replies are listed 'Best First'.
Re^6: Advanced Bubble Sort
by AnomalousMonk (Archbishop) on Oct 17, 2016 at 07:31 UTC

    FWIW, here's my latest take on the problem. I also have some doubt about what a "version string" is in this context, but like you, I take, e.g., "4.2.12-7" to be a version string with four components. I also wanted to investigate the single pass, no sort approach. The following solution also retains input order a-la List::MoreUtils::uniq(). (I have no idea if these latter features are required or desired at all, but I wanted to play around with them just as an intellectual exercise.) I can't say I really like this code; three of the map statements | expressions are rather hairy (one is quite long) and I'd hate to be the one who has to maintain this code. Anyway:

    use warnings; use strict; use Data::Dump qw(dd); use Test::More 'no_plan'; use Test::NoWarnings; my $ver = qr{ - (\d+) [.] (\d+) [.] (\d+) - (\d+) [.] }xms; my %latest; my @most_recent = map $latest{ $_->[0] }[1] eq $_->[2] ? $_->[2] : (), map { $latest{$_->[0]} = [ @$_[1,2] ] if ! $latest{$_->[0]} or $la +test{$_->[0]}[0] lt $_->[1]; $_; } map [ (m{ \A (.*?) $ver }xms)[0], pack('N4', m{$ver}xms), $_ ], map validate($_), map { chomp; $_; } <DATA> ; dd \@most_recent; is_deeply \@most_recent, [ qw( samba-common-libs-4.2.12-7.el7_2.x86_64 abc-4.2.11-10.el7_2.x86_64 xyz-libs-4.2.13-7.el7_2.x86_64 )], "extracted by most recent version"; done_testing; sub validate { return $_[0]; } # data from Marshall pm#1174121 # also added: # samba-common-libs-4.2.9-8.el7_2.x86_64 # abc-4.2.11-10.el7_2.x86_64 __DATA__ samba-common-libs-4.2.12-7.el7_2.x86_64 samba-common-libs-4.2.10-3.el7_2.x86_64 xyz-libs-4.2.10-7.el7_2.x86_64 samba-common-libs-4.2.10-6.el7_2.x86_64 abc-4.2.11-7.el7_2.x86_64 samba-common-libs-4.2.9-8.el7_2.x86_64 abc-4.2.11-10.el7_2.x86_64 xyz-libs-4.2.11-7.el7_2.x86_64 abc-4.2.11-8.el7_2.x86_64 samba-common-libs-4.2.10-6.2.el7_2.x86_64 xyz-libs-4.2.12-7.el7_2.x86_64 xyz-libs-4.2.13-7.el7_2.x86_64 samba-common-libs-4.2.10-8.el7_2.x86_64
    (This runs under 5.8.9.)

    Output:

    c:\@Work\Perl\monks\Anonymous Monk\1173958>perl sort_by_ver_latest_3.p +l [ "samba-common-libs-4.2.12-7.el7_2.x86_64", "abc-4.2.11-10.el7_2.x86_64", "xyz-libs-4.2.13-7.el7_2.x86_64", ] ok 1 - extracted by most recent version 1..1 ok 2 - no warnings 1..2


    Give a man a fish:  <%-{-{-{-<