פרק 10: ניהול רשימות והאשים (Hashs)כל סוגי המיונים: רשימותלעיתים, סדר החפצים משנה... לדוגמא בסידור אלפביתי של שמות אנשים, או בסידור נומרי של מחירים, או תוצאות מבחנים. פונקצית ה sort של Perl מאפשרת שליטה מצוינת על אופן מיון המידע. נתחיל ברשימות, ברירת המחדל של תחביר הפונקציה sort היא מיון אלפביתי של רשימת נתונים, המחזיר את הרשימה הממוינת כפלט. @names=("Mark","Wendy","John"); foreach $name (sort @names) { print "$name\n" } בלוק ה foreach שלמעלה ידפיס רשימת שמות בסדר ממוין, "John", "Mark" ו "Wendy". תוצאות אלו לא יהיו מושלמות אם נשתמש במספרים: @grades=(80,100,95); foreach $grade (sort @grades) { print "$grade\n" } התוצאה תהיה 100, 80, 95 ההסבר בהמשך! ברירת המחדל של פונקצית המיון (Sort) היא מיון אלפביתי, ובמיון כזה 100 אכן בא לפני 80 (1 לפני 8). אנו זקוקים למיון מספרי...למעשה פונקצית ה sort נותנת אפשרות למיון ע"פ כל קריטריון בו תרצו. אתם יכולים לספק את הקוד של קריטריוני המיון ו sort תספק שני ערכים a$ ו b$. הקוד שלכם אמור להשתמש בשני הערכים הללו לבחינת כל קריטריון בו תרצו, כאשר הפלט שלו צריך להיות שלם חיובי כלשהו במידה וa$ נמצא לפני b$ במיון, שלם שלילי אם b$ נמצא לפני a$ או אפס אם שני הערכים שווים. זה נשמע מסובך ממה שזה באמת: foreach $grade (sort {$a<=>$b} @grades) { print "$grade\n" } כאן הוספנו קוד לפונקצית ה sort. הקוד משווה בין a$ ל b$ ע"י אופרטור "השוואת שלושת הכיוונים" (three-way comparison)אשר ידוע גם כאופרטור החללית (spaceship operator). סמל ה <=> הוא קיצור של Perl אשר מחזיר 1,0+ או 1- בהשוואה נומרית בין$a ל $b. כעת נקבל פלט נכון: 80,95,100. נניח ורציתם למיין בסדר הפוך? המיון הנומרי שלנו מדויק אולם אנו רוצים את התוצאות בסדר יורד: 100,95,80. בקלות! רק הכניסו את המילה reverse (הפוך), לפני פונקצית ה sort, והתוצאה תמויין ותוחזר בסדר הפוך. foreach $grade (reverse sort {$a<=>$b} @grades) { print "$grade\n" } במקום להכניס את פונקצית המיון שלנו לתוך פונקצית ה sort כמו שעשינו, אנו יכולים לקרוא לפונקציה שתבצע את ההשוואה במידה והיא מסובכת יותר. כדוגמא, דמיינו לעצמכם רשימה מלאה בשמות: @names=("john wallace","mike wallace","harris bluebaum", "gorky yeller","yehva stuntz"); אנו רוצים למיין רשימה זו ע"פ שמות המשפחה ואחר כך ע"פ השמות הפרטיים - אנו זקוקים לפונקציה שתבצע השוואות אלו ותקרא מתוך פונקצית ה sort. foreach $name (sort by_lastname @names) {print "$name\n"} sub by_lastname { ($a_firstname,$a_lastname)=$a=~/^(\w+)\s+(\w+)$/; ($b_firstname,$b_lastname)=$b=~/^(\w+)\s+(\w+)$/; $sortResult=$a_lastname cmp $b_lastname; if ($sortResult == 0) { $sortResult=$a_firstname cmp $b_firstname } return $sortResult; } הקריאה ל sort שולחת a$ ו b$ לתוך הפונקציה by_lastname. בתוך הפונקציה אנו מחלקים את השמות לשם פרטי ולשם משפחה בעזרת התאמת ביטויים רגולריים. לאחר מכן שמות המשפחה משווים ע"י אופרטור ה cmp, אשר מהווה עוד דרך ל "השוואת שלושת הכיוונים", המקבילה המחרוזתית של האופרטור הנומרי <=> . אם cmp מחזירה אפס אנו מבינים ששני שמות המשפחה זהים, ולכן אנו ממשיכים ומשווים את השמות הפרטיים. כאשר הפונקציה מסיימת התוצאות מוחזרות חזרה לפונקצית ה sort. וכן...זה עובד! אני מקווה שפונקצית ה by_lastname מדגימה לכם שהשוואת ה sort שלכם יודעת לבצע כל פעולה שתזדקקו לה על מנת להשוות בין הערכים a$ ו b$. למעשה, זה אף לא צריך להתבצע בצורה ישירה, למשל מצב בו תשתמשו ב a$ ו b$ על מנת להתבונן במבנה נתונים אחר כמו האש, או אף בבסיס נתונים מתעדכן, ובהתבסס על הנתונים במבנה להחליט מי מבין a$ ו b$ גדול יותר. כמו שאומרים על LEGO, האפשרויות הן בלתי מוגבלות. תזכורת:
רשימות וטבלאות האש
|