sort#
ממיין רשימה, ומחזיר את הרשימה הממוינת.
sort לוקח רשימה ומחזיר רשימה חדשה עם האלמנטים מסודרים בסדר. ללא משווה הוא משתמש בהשוואת מחרוזות סטנדרטית. עם BLOCK או SUBNAME אתם מספקים את כלל ההשוואה כפונקצייה קטנה שנקראת עבור כל זוג אלמנטים וחייבת להחזיר ערך שלילי, אפס, או חיובי באופן ש־cmp ו־<=> עושים.
המיון יציב - אלמנטים שמשוים שווים שומרים על הסדר היחסי המקורי שלהם. האלגוריתם הוא mergesort.
תקציר#
sort LIST
sort BLOCK LIST
sort SUBNAME LIST
שלוש צורות אידיומטיות:
my @out = sort @in; # default: string cmp, ascending
my @out = sort { $a <=> $b } @in; # numeric, ascending
my @out = sort by_name @in; # named comparator sub
מה מקבלים בחזרה#
רשימה ממוינת חדשה. sort אינו משנה את הקלט במקום. כדי להחליף מערך בגרסה הממוינת שלו עליכם להשים בחזרה:
@a = sort @a;
בהקשר רשימה ההחזרה היא הרשימה הממוינת. בהקשר סקלרי ערך ההחזרה לא־מוגדר - אל תשתמשו ב־scalar sort.
הרשימה המוחזרת מכילה aliases לתוך הרשימה המקורית, בדיוק כמו משתנה אינדקס של foreach. שינוי אלמנט של התוצאה בתוך foreach, map, או grep מאוחר משנה לכן גם את האלמנט המקורי. זה כמעט אף פעם אינו מה שרוצים; התייחסו לתוצאה כקריאה־בלבד.
מצב גלובלי: $a ו־$b#
בתוך ה־BLOCK או SUBNAME של המשווה, שני האלמנטים המושווים נחשפים כגלובלים של חבילה $a ו־$b. אלה אינם פרמטרים והם אינם לקסיקליים - הם משתני חבילה אמיתיים ש־sort עושה להם localize סביב הקריאה.
$aו־$bחיים בחבילה שקראה ל־sort. ב־main, זה$main::aו־$main::b; ב־Foo,$Foo::aו־$Foo::b.לעולם אל תצהירו על
my $aאוmy $bבכל מקום שבלוק המיון יכול לראות.$aאו$bלקסיקליים מצלים על הגלובלי של החבילה; הבלוק אז משווה שני משתנים לא־קשורים והמיון מפיק בשקט זבל. תחתuse warningsאינכם מקבלים אזהרה על כך.אם אתם זקוקים באמת ל־
$a/$bכלקסיקליים במקום אחר, התייחסו למשתני המיון בשם המלא בתוך הבלוק:print sort { $::a cmp $::b } qw(A C E G B D F H); print sort { our $a cmp our $b } qw(A C E G B D F H);
משווה המוגדר עם ה־prototype
($$)(או אטריבוט חתימה מקביל) מקבל את הזוג ב־@_במקום ב־$aו־$b. זה איטי יותר ממוסכמת$a/$bאבל מנתק את תת־השגרה מהחבילה של הקורא.
שני האלמנטים מועברים בהפניה; שינוי $a או $b בבלוק משנה את הרשימה המקורית. אל תעשו זאת.
דוגמאות#
מיון מחרוזות ברירת מחדל:
my @sorted = sort qw(banana apple cherry);
# ('apple', 'banana', 'cherry')
מספרי עולה - ברירת המחדל sort @nums תמיין את "10" לפני "2" כי ההשוואה היא לפי מחרוזת:
my @nums = sort { $a <=> $b } (10, 2, 33, 4);
# (2, 4, 10, 33)
מספרי יורד - להחליף את $a ו־$b:
my @nums = sort { $b <=> $a } (10, 2, 33, 4);
# (33, 10, 4, 2)
מיון רב־מפתחות עם שובר־שוויון. || מריץ את המשווה השני רק כאשר הראשון מחזיר 0:
my @people = sort {
$a->{last} cmp $b->{last}
|| $a->{first} cmp $b->{first}
} @records;
מיון מפתחות של האש לפי הערך המקושר:
my %age = (alice => 30, bob => 25, carol => 40);
my @by_age = sort { $age{$a} <=> $age{$b} } keys %age;
# ('bob', 'alice', 'carol')
טרנספורם שוורצי - כאשר מפתח המיון יקר לחישוב, חשבו אותו פעם אחת לכל אלמנט, מיינו את זוגות [key, value], ואז הסירו את המפתחות. שלושה שלבים, לקרוא מלמטה למעלה:
my @sorted =
map { $_->[1] } # 3. strip key
sort { $a->[0] <=> $b->[0] } # 2. sort by key
map { [ expensive_key($_), $_ ] } # 1. attach key
@input;
תת־שגרת משווה בעלת שם. תת־השגרה קוראת $a ו־$b מחבילת הקורא, אז היא חייבת להיות באותה חבילה (או להיות מקושרת ממנה):
sub by_name { $a->{name} cmp $b->{name} }
my @sorted = sort by_name @people;
משווה עם prototype - הארגומנטים מגיעים ב־@_, אז הוא עובד מכל חבילה:
sub numeric ($$) { $_[0] <=> $_[1] }
my @sorted = sort numeric @nums;
מקרי קצה#
$aו־$bהם גלובלים של חבילה, לא לקסיקליים.my $aתועה בתחום שובר בשקט כל מיון באותו תחום. אם עליכם, השתמשו ב־our $aאו ב־$::aבתוך הבלוק.<=>מספרי,cmpמחרוזתי. שימוש בלא־נכון הוא באג המיון הנפוץ ביותר.sort { $a cmp $b } (10, 2, 33)מניב(10, 2, 33)- לקסיקוגרפי,"10"לפני"2". השתמשו ב־<=>למספרים.רשימה ריקה מחזירה רשימה ריקה.
sort ()הוא(). אין שגיאה.אלמנט בודד מוחזר ללא שינוי. אין השוואות.
המשווה חייב להיות עקבי. אם הוא לפעמים אומר
$x < $yולפעמים אומר את ההפך עבור אותו זוג, התוצאה לא־מוגדרת. המשווה חייב להחזיר סדר טוטלי: שלילי, אפס, או חיובי, באופן יציב, לכל קריאה.NaNמרעיל את<=>.$a <=> $bמחזירundefאם אחד מהאופרנדים הואNaN, ש־sortאז מתייחס אליו כ־0- שווה - נותן מיקום שרירותי. סננו תחילה:my @clean = sort { $a <=> $b } grep { $_ == $_ } @input;
מיון יציב. אלמנטים שווים שומרים על סדר הקלט שלהם. הסתמכו על זה למיונים רב־מעבריים (מיון לפי מפתח משני תחילה, ואז לפי מפתח ראשי).
use sort 'stable'הוא ברירת המחדל וחסר־פעולה; פראגמותuse sort '_mergesort'/'_qsort'הן היסטוריות ואין להן השפעה על Perl הנוכחי.sortאינו במקום.sort @aאינו נוגע ב־@a. השתמשו ב־@a = sort @aכדי להחליפו. השמה לרשימת התוצאה שלsortיוצרת alias בחזרה למקור, אז(sort @a)[0] = ...משנה את האלמנט הקטן ביותר של@a.No loop control out of the block.
last,next,redo,return, andgoto LABELdo not work inside a sort comparatorthe block is not a loop body.
מלכודת מפענח: מיון ערך החזרה של פונקצייה.
sortלוקחLIST, אז bareword בא אחריו יכולה להיות מובנת בטעות כ־SUBNAME. למיון התוצאה שלfind_records(@key):my @out = sort { $a cmp $b } find_records @key; # OK my @out = sort +find_records(@key); # OK my @out = sort(find_records(@key)); # OK
לשימוש ב־
find_recordsכמשווה על@keyבמקום:my @out = sort find_records @key; # comparator form my @out = sort { find_records() } @key; # block form
מיון מודע locale. תחת
use locale(ללא':not_characters') השוואת המחרוזות ברירת המחדל עוקבת אחר ה־collation locale הנוכחי במקום סדר נקודות הקוד.משווי XSUB. אם המשווה הוא XSUB, הזוג מועבר על מחסנית הארגומנטים באופן שפונקציות XS מקבלות ארגומנטים בדרך כלל;
$aו־$bאינם נקבעים.
הבדלים מהמקור#
תאימות מלאה עם Perl 5.42 המקורי.
ראו גם#
reverse- היפוך רשימה; שלבו עםsortלמיונים יורדים כאשר המשווה קשה להיפוך על־ידי החלפת$aו־$bmap- החצי השני של הטרנספורם השוורצי; השתמשו לחיבור והסרת מפתחות מיון סביבsortgrep- סינון מקדים של הרשימה (למשל הסרתNaNאוundef) לפני העברתה ל־sort$a- האלמנט הראשון בזוג ההשוואה, ב־alias כגלובלי של חבילה למשך המיון$b- האלמנט השני בזוג ההשוואה, אותם כללי משך־חיים ותיחום כמו$a<=>- השוואה מספרית תלת־כיוונית; האופרטור הרגיל בתוך בלוק מיון מספריcmp- השוואת מחרוזות תלת־כיוונית; האופרטור הרגיל בתוך בלוק מיון מחרוזות