במאמר זה נראה כיצד ניתן למיין מערך של מספרים או של מחרוזות בפרל.

לפרל יש פונקציה מובנית שנקראת sort ואין זה מפתיע שהיא יודעת למיין מערך. בצורתה הפשוטה ביותר - נותנים לה מערך והיא מחזירה את האלמנטים במערך כשהם ממוינים. @sorted = sort @original.

מיון המבוסס על סדר ASCII

#!/usr/bin/perl
use strict;
use warnings;
use 5.010;

use Data::Dumper qw(Dumper);

my @words = qw(foo bar zorg moo);

say Dumper \@words;

my @sorted_words = sort @words;

say Dumper \@sorted_words;

הדוגמה לעיל תדפיס את הפלט הבא:

והתוצאה היא:

$VAR1 = [
        'foo',
        'bar',
        'zorg',
        'moo'
      ];

$VAR1 = [
        'bar',
        'foo',
        'moo',
        'zorg'
      ];

הפלט הראשון מציג את המערך לפני המיון, הפלט השני מציג את המערך אחרי המיון.

זו הדוגמה הפשוטה ביותר, אבל זה לא תמיד מה שאנחנו רוצים. למשל מה קורה אם חלק מהמלים מתחילות באותיות גדולות?

my @words = qw(foo bar Zorg moo);

התוצאה ב-@sorted_words תהיה:

והתוצאה היא:

$VAR1 = [
        'Zorg',
        'bar',
        'foo',
        'moo'
      ];

כפי שאתם רואים, המילה שמתחילה באות גדולה הופיעה ראשונה. הסיבה לכך היא שכברירת מחדל sort, ממיינת על פי הסדר בטבלת ASCII , וכל האותיות הגדולות נמצאות לפני כל האותיות הקטנות.

פונקציות השוואה

פונקצצית sort עובדת בפרל באופן הבא: היא עוברת על כל זוג אלמנטים של המערך המקורי; בכל מעבר היא מציבה את הערך מהצד השמאלי במשתנה$a, ואת הערך מהצד הימני במשתנה $b. אז היא קוראת לפונקציית השוואה. "פונקציית ההשוואה" תחזיר 1 אם התוכן של $a צריך להיות מצד שמאל, 1- אם התוכן של $b צריך להיות מצד שמאל, או 0 אם זה לה משנה כיוון ששני הערכים זהים.

כברירת מחדל לא רואים את פונקציית ההשוואה והפונקצייה sortמשווה את הערכים לפי טבלת ה- ASCII , אבל אם אתם רוצים, אפשר לכתוב זאת במפורש:

sort { $a cmp $b } @words;

התוצאה של קוד זה תהיה זהה לקוד שנכתב ללא הבלוק: sort @words.

ניתן לראות כאן שכברירת מחדל פרל משתמשת בפונקצייה cmp בפונקציית ההשוואה. הסיבה לכך היא ש cmp עושה בדיוק את מה שאנחנו צריכים כאן. היא משווה את הערכים משני צידיה כמחרוזות, מחזירה 1 אם הערך השמאלי "קטן" מהערך הימני, היא מחזירה 1- אם הערך השמאלי "גדול" מהימני, ומחזירה 0 אם הם שווים.

מיון לפי סדר אלפביתי

אם אתם רוצים להתעלם מההבחנה בין אותיות וגדולות - כלומר למיין על פי מה שלרוב נקרא סדר אלפביתי - אתם יכולים לעשות זאת באמצעות הקוד הבא:

my @sorted_words = sort { lc($a) cmp lc($b) } @words;

במקרה זה, לצורך ההשוואה, אנחנו קוראים לפונקצייה lc שמחזירה את הגירסה של המחרוזת באותיות קטנות . הפונקצייה cmp משווה את גירסאות האותיות הקטנות של המחרוזות ומחליטה איזו מהמחזורות המקוריות צריכה להיות קודם.

התוצאה היא

והתוצאה היא:

$VAR1 = [
        'bar',
        'foo',
        'moo',
        'Zorg'
      ];

מיון מספרים בפרל

אם ניקח מערך מספרים ונמיין אותם עם ברירת המחדל של המיון, התוצאה כנראה לא תהיה מה שאנחנו מצפים.

my @numbers = (14, 3, 12, 2, 23);
my @sorted_numbers = sort @numbers;
say Dumper \@sorted_numbers;

והתוצאה היא:

$VAR1 = [
        12,
        14,
        2,
        23,
        3
      ];

כמובן שאם תחשבו על זה תיראו שזה לא ממש מפתיע. כשפונקציית המיון רואה 12 ו-3 היא משווה אותם כמחרוזות כלומר קודם כל היא משווה את התו הראשון בשתי המחרוזות. "1" ו- "3". "1" קודם ל-"3" בטבלת ה- ASCII ולכן המחרוזת "12" תהיה לפני המחרוזת "3".

פרל לא מבינה לבד שאתם רוצים למיין את הערכים כמספרים.

אבל זאת לא בעיה, כיוון שאפשר לכתוב פונקציית השוואה שתשווה את שני הערכים כמספרים. לצורך זה נשתמש באופרטור <=> (שנקרא גם spaceship operator - אופרטור ספינת החלל) שמשווה את שני הפרמטרים כמספרים ומחזיר 1 , 1- או 0.

my @sorted_numbers = sort { $a <=> $b } @numbers;

Results in:

והתוצאה היא:

$VAR1 = [
        2,
        3,
        12,
        14,
        23
      ];