1 / 13

Sorting

Sorting. Simple Sorting.

chloe
Télécharger la présentation

Sorting

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Sorting

  2. Simple Sorting • As you are probably aware, there are many different sorting algorithms: selection sort, insertion sort, bubble sort, heap sort, quick sort, etc. You can spend a lot of time writing sort functions if you are so inclined. However, most of us have better things to do, and so Perl provides a good general purpose “sort” function, that uses the standard quick sort algorithm. In most cases it will be quite efficient and fast enough for your purposes. • By default, the Perl sort function sorts by ASCII order. Thus, the command my @sorted_array = sort @array; puts the elements of @array into ASCII-sorted order in @sorted_array.

  3. Sort Function • The way in which the “sort” determines ordering can be altered by putting a user-defined subroutine or a block of code between the word “sort” and the list (or array) of things to be sorted: sort user_sub @arr; sort {code block} @arr; • The subroutine or block goes through the array and compares each pair of elements in the array. It returns a negative number if the first element is less than the second, zero if the two elements are equal, and a positive number if the first element is greater than the second element. • The input to the subroutine or block is fixed: two variables, called $a and $b. Note that these names are fixed: $a is the first element to be compared, and $b is the second element. $a and $b should not be modified by the subroutine. • A simple comparison bloc for a numerical sort: sort { $a - $b } @arr; If $a (first element) is greater that $b, a positive number is returned; 0 is returned if they are equal, and a negative number is returned if $b is greater than $a.

  4. Built-in Comparison Operators • Perl includes 2 built-in operators that give the correct results for sorting numbers or strings. • For numerical comparisons, <=> (sometimes called the “spaceship” operator) is used. The standard numerical sort is written: sort {$a <=> $b} @arr; • For string comparisons, cmp is used. For an ASCII sort you can use the following (although it is the default and not necessary to write is a simple sort): sort {$a cmp $b } @arr;

  5. Blocks vs. Subroutines • The sort routine can be a block of code, enclosed by curly braces {}, or it can be a subroutine defined elsewhere. Which you use is a matter of taste. If the routine is long and complex, a subroutine might be more appropriate, but for simple and short methods, a block is easier. • Thus, these two are equivalent: sort {$a <=> $b } @arr; sort numerically @arr; sub numerically { return $a <=> $b; }

  6. Reverse Sort • By default, sorting is done from smallest to largest. The simplest way to sort from largest to smallest is to simply reverse $b and $a in the sort routine block: numerical: sort {$b <=> $a} @arr; ASCII: sort {$b cmp $a} @arr;

  7. Sorting Hash Keys • A common problem is to sort the keys of a hash by the values they refer to, for instance to print them in proper order. • The trick is to put the keys into an array, then use those keys to access the hash’s values. For example: my @keys = keys %hash; my @sorted_keys = sort {$hash{$a} <=> $hash{$b} } @keys; • Here, each pair of hash keys is taken from @keys and substituted into the sort routine, and a sorted list of keys is outputted. • it is necessary to put the sorted keys into an array because hash keys are not stored in a fixed order. • The original @keys array isn’t necessary. This will also work: my @sorted_keys = sort {$hash{$a} <=> $hash{$b} } keys %hash;

  8. Sorting Array Indices • If you have several parallel arrays that you wish to sort simultaneously, you need to create a list of array indices in the sorted order. The procedure is very similar to sorting hash keys. my @sorted_ind = sort { $arr[$a] <=> $arr[$b] } 0 .. $#arr; • Here, the indices are accessed through 0 .. $#arr. They are then used to compare the actual array elements, and then put into the “@sorted_ind” array. You can then use this array of indices to sort any other arrays in the same order: my @sorted_arr = @arr[@sorted_ind]; my @second_sorted_arr = @second_arr[@sorted_ind]; • This procedure uses an “array slice”, a list of indices inside the square braces instead of a single index value.

  9. Example • You have 3 arrays of student data: @id = (57880, 74675, 13892, 20051, 18834); @names = qw(Ahmed Anderson Blackwell Chilson Coburn); @grades = qw(A C B F B); • You want to sort all of them in parallel, by ID number. @sorted_ind = sort {$id[$a] <=> $id[$b]} 0 .. $#id; # @sorted_ind is (2, 4, 3, 0, 1; @id = @id[@sorted_ind]; @names = @names[@sorted_ind]; @grades = @grades[@sorted_ind];

  10. Sorting by Two or More Criteria • You want to sort first by one criterion, then resolve ambiguities using a second criterion. For example, sort by last name, then by first name if necessary. • To do this, use the “or” operator || between the two comparisons. If the first comparison returns 0 (because they are equal), then do the second comparison. The second is not done if the first comparison returns a TRUE value (i.e. non-zero). @last_names = qw(Coburn Smith Jones Jones Smith); @first_names = qw(Fred Harold Mary Jane Hortense); @sorted_ind = sort {$last_names[$a] cmp $last_names[$b] || $first_names[$a] cmp $first_names[$b] } 0 .. $#last_names; • Then use the sorted indices to put both arrays in the proper order.

  11. Grep • grep is a useful function taken from Unix. It takes an array as an argument, tests each array element, and returns a list of those elements for which the test is true. • grep puts each element of the array into $_ for the test. This is similar to a “foreach” loop. • A typical example: return all words in a list containing “th”: @arr = qw(the dog went in there); @th_arr = grep /th/, @arr; # @th_arr is (“the”, “there”) • This is equivalent (but much shorter than): foreach (@arr) { push @th_arr if ($_ =~ /th/); } • You can use either an expression or a block as the test. Note that you must put a comma after an expression (before the list of elements), but NOT after a block enclosed by curly braces. Thus, this is equivalent to the above: @th_arr = grep { /th/ } @arr; • The expression or block must return either a true value or a false value when it is evaluated with $_.

  12. Grep Used to Determine Membership in a List • A good use for grep is determining whether a string or number is present in a list. • in a scalar context, grep returns the number of times the test expression is true. • In a list context, grep returns a list of the array items for which the test expression is true. my @pets = qw(cat dog ferret gerbil rabbit); my $animal = <STDIN>; if (grep $_ = $aminal, @pets) { print “I have a $animal\n”; } else { print “I don’t have a $animal\n”; } • grep is being used in a list context: if $animal matches anything on the list @pets, grep will return a value of 1 or more. If nothing matches, grep returns 0 (false).

  13. Map • map is another useful function related to grep. map takes each element of a list or array, substitutes them in turn into $_, and performs some function on them. • As with grep, map is simply a shorter way of writing something you could do with a foreach loop. • A simple example: adding 3 to each element of an array: @arr = map {$_ += 3} @arr; • Just like grep, map can use either an expression (followed by a comma), or a block (no comma). • map can return more than one value for each input value. All returned values end up on a single list, however. • For example, this function returns a 1, followed by the original value, followed by the square of that value. This function has a real use in multivariate statistics, by the way. @new_arr = map { 1, $_, $_ ** 2} @arr;

More Related