简体   繁体   中英

Perl sorting and regular expressions

I have an array that contains values like this:

@array = 
("2014 Computer Monitor 200",
"2010 Keyboard 30",
"2012 Keyboard 80",
"2011 Study Desk 100");

How would I use regular expressions in Perl to sort the entire array by year, item name, and price? For example, if the user wants to sort by price they type 'price' and it sorts like this:

2010 Keyboard 30
    2012 Keyboard 80
    2011 Study Desk 100
    2014 Computer Monitor 200

So far I've been able to sort by year like this:

@array = 
    ("2014 Computer Monitor 200",
    "2010 Keyboard 30",
    "2012 Keyboard 80",
    "2011 Study Desk 100");
    
    $input = ;
    
    chomp($input);
    if ($input eq "year")
    {
        foreach $item (sort {$a cmp $b} @array)
        {
        print $item . "\n";
        }
    }

/(\\d+) \\s+ (.+) \\s+ (\\S+)/x will match year name and price,

use strict;
use warnings;

my $order = "price";
my @array = (
  "2014 Computer Monitor 200",
  "2010 Keyboard 30",
  "2012 Keyboard 80",
  "2011 Study Desk 100"
);

my %sort_by = (
  year  => sub { $a->{year}  <=> $b->{year} },
  price => sub { $a->{price} <=> $b->{price} },
  name  => sub { $a->{name}  cmp $b->{name} },
);
@array = sort {

  local ($a, $b) = map {
    my %h; 
    @h{qw(year name price)} = /(\d+) \s+ (.+) \s+ (\S+)/x;
    \%h;
  } ($a, $b);
  $sort_by{$order}->();

} @array;

# S. transform
# @array =
#  map { $_->{line} }
#  sort { $sort_by{$order}->() }
#  map { 
#    my %h = (line => $_); 
#    @h{qw(year name price)} = /(\d+) \s+ (.+) \s+ (\S+)/x;
#    $h{name} ? \%h : ();
#  } @array;

use Data::Dumper; print Dumper \@array;

output

$VAR1 = [
      '2010 Keyboard 30',
      '2012 Keyboard 80',
      '2011 Study Desk 100',
      '2014 Computer Monitor 200'
    ];

Using a sort without a transform:

use strict;
use warnings;

my @array = ( "2014 Computer Monitor 200", "2010 Keyboard 30", "2012 Keyboard 80", "2011 Study Desk 100" );

my $order = "price";

my @sorted = sort {
    local ( $a, $b ) = map { /^(?<year>\d+) \s+ (?<name>.*) \s (?<price>\d+)/x ? {%+} : die "Can't parse $_" } ( $a, $b );
    ($order ne 'name' ? $a->{$order} <=> $b->{$order} : 0) || $a->{name} cmp $b->{name}
} @array;

print "$_\n" for @sorted;

Outputs:

2010 Keyboard 30
2012 Keyboard 80
2011 Study Desk 100
2014 Computer Monitor 200

Note: If one is sorting more than 10k items, efficiency might become a concern and one can utilize a https://en.wikipedia.org/wiki/Schwartzian_transform

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM