I'm looking for an elegant solution to sort an array and then replace the numerical values with letters. I got something working here but it is a huge if/else monster that, I'm sure, can be written much shorter.
Sample code:
my $values = "70,20,50";
my @singlevalues = sort(split(/,/,$values));
ifmonster();
my $result = "RBG";
$valu开发者_高级运维es
has three color values in it, where the first one represents "R", the second one "G" and the last one "B". I want to sort these values and in the end get a string like $result
which is sorted form biggest to smallest represent by the letters.
So "70,20,50" results in "RBG" while "20,50,30" results in "GBR".
Thank you
A hashless solution:
my @color = split /,/, $value, 3;
my @order = sort { $color[$b] <=> $color[$a] } 0..2;
my $result = join "", qw(R G B)[@order];
The @order
list stores a permutation which is later applied to the letter list.
It sounds like a hash would store the data in the way you want to access it. Building it is fairly simple:
#!/usr/bin/perl
use strict;
use warnings;
my $values = "70,20,50";
my %components_by_name;
@components_by_name{qw/R G B/} = split ",", $values;
my $result = join "",
sort { $components_by_name{$b} <=> $components_by_name{$a} }
keys %components_by_name;
print "$result\n";
You can declare an empty hash by saying:
my %hash;
When assigning to a hash you can say
$hash{key} = "value";
But if assigning a bunch of values whose keys you know in advance, it is often easier to use a hash slice:
@hash{"key 1", "key 2", "key 3"} = ("value 1", "value 2", "value 3");
If your keys don't contain whitespace, you can use the qw//
operator to reduce the amount of noise on the line
@hash{qw/key1 key2 key3/} = ("value 1", "value 2", "value 3");
Accessing a value in a hash is similar to how you access values in an array, but you use {}
instead of []
and the key is a string instead of a number:
my $value = $hash{key1}; #$value now holds "value 1";
To get all of the keys in a hash, you can use the keys
function:
my @keys = keys %hash;
Try this
#!/usr/local/bin/perl
my $values = "70,20,50";
my @singlevalues = split(/,/,$values);
my %colourMap = ();
$colourMap{$singlevalues[0]} = 'R';
$colourMap{$singlevalues[1]} = 'G';
$colourMap{$singlevalues[2]} = 'B';
foreach $key(sort {$b <=> $a} keys %colourMap)
{
$result = $result . $colourMap{$key};
}
print $result;
my %hash;
my $values = "70,20,50";
@hash{split(/,/,$values)} = qw/R G B/;
print @hash{sort keys %hash};
This works for your specific example. I will leave it to you to generalize. :)
my $values = "70,20,50";
my @values = split(/,/,$values);
my $hash = {$values[0] => "R", $values[1] => "G", $values[2] => "B"};
print(join("", (map {$hash->{$_}} (sort { $b <=> $a } @values))));
print "\n";
(Edited to fix the problem found by Chas Owens in the comments below.)
Here's a plot of yet another method (though it's probably the C way): reduce the ifmonster to a set of logical operations and pick the right answer from a predefined array.
# defined once
our @rgbindex = qw(RGB GRB null GBR RBG null BRG BGR);
# later, e.g. in a sub
my ($r, $g, $b) = split /,/, $values;
my $i = (($r < $g) ? 1 : 0)
+ (($r < $b) ? 2 : 0)
+ (($g < $b) ? 4 : 0);
return $rgbindex[$i];
The null
s in @rgbindex appear because they correspond to illegal setups. (And also 2^3 (number of bit combos) = 8, but 3! (the number of permutations) is only 6)
精彩评论