开发者

Replace and sort perl array elements

开发者 https://www.devze.com 2023-03-22 21:15 出处:网络
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 m

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 nulls 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)

0

精彩评论

暂无评论...
验证码 换一张
取 消