Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How do you compare values in an array?

Status
Not open for further replies.

FinnMan

Technical User
Feb 20, 2001
75
US
How do you compare values in an array if you do not know how many values the array will contain?
 
Not quite sure what you are comparing the values to, but here goes.
Code:
# Method 1
foreach $Item (@Array) {
    if ($Item == $Value) { # Numeric comparison
    # if ($Item eq $Value) { # String comparison
        do something
    }
}
# Method 2
@Match = grep /^$Value$/, @Array;
if ($#Match >= 0) {
    do something
}
 
Well, I've gotten that far :)

What I'm trying to do is dump all the values in an array compare those values to each other, and then print the greatest value. So the part I'm having trouble with is that $value is unknown.
 
Assuming you don't need the index of the largest value, the easiest way would be to do a sort.
Code:
@Sorted = sort {$a <=> $b } @Array; # Ascending order
print &quot;The largest value is $Sorted[$#Sorted]\n&quot;;
print &quot;The smallest value is $Sorted[0]\n&quot;;
FYI, to get descending order 'sort {$b <=> $a} @Array'.

If you need to know the index of the largest value, the following will do the trick.
Code:
$Largest = $Array[0];
$Index = 0;
for ($i=1; $i<=$#Array; $i++) {
    if ($Array[$i] > $Largest) {
        $Largest = $Array[$i];
        $Index = $i;
    }
}
print &quot;The largest value $Largest is at index $Index\n&quot;;
 
You could also have a look at the Schwartzian Transform:

my @output =
map { $_->[0] }
sort { $a->[1] cmp $b->[1] }
map { [$_, expensive_func($_)] }
@input;


The Schwartzian Transform is a sort bracketed by map operators. The first (textually &quot;last&quot; - line 4 of the code above) map operator, map { [ $_, -M ] }, turns a list of scalar filenames into a list of array references. Each array ref points to a 2-element list, containing the original element ($_) and its transformed value (-M). The sort operator then sorts the list of array references -- $a->[1] and $b->[1] are references to the transformed values pointed to by $a and $b. A second map operator, map { $_->[0] }, &quot;slices&quot; the original values, now in sorted order, out of the list of array references.

The purpose of the Schwartzian Transform is to temporarily cache the results of expensive key transformations (like -M or split) so that they are only computed once, not n log n times, for each item being sorted. The beauty of the Schwartzian Transform is that it accomplishes this task in a single expression without using even one named temporary!

If you're not familiar with the map operator and/or anonymous arrays, this may seem very confusing at first. In that case, take a look at Randal's somewhat longer (and illustrated!) explanation at which appears to be down at the moment :(.

Adapting the Schwartzian transform to your own uses is simple. Just replace the transform function and make sure that you are using the correct sort operator (<=> for numbers, cmp for strings).

The beauty of the sort is that it stores everything in temporary variables and only evaluates each once.

Once you get head around what it's doing you can adapt it to most sorting procedures. At least that's what Randal says.

HTH,
Barbie. Leader of Birmingham Perl Mongers
 
Thx for the wonderful help guys!

Any idea how I could extract a value from being in the equation if I know that value ahead of time so that it's not counted in the sort?
 
Here's one way:
Code:
@Sorted = sort {$b <=> $a } @Array; # Descending
if ($Sorted[0] == $Known) {
    $Largest = $Sorted[1]; # Ignore known value
} else {
    $Largest = $Sorted[0];
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top