אופרטורי השוואת מחרוזות#
המקבילות בטעם־מחרוזת של משפחת ההשוואה המספרית. אותה צורה, אותה שורת קדימות, אך פועלות לקסיקוגרפית (סדר נקודות־קוד של Unicode בברירת מחדל) במקום מספרית.
אופרטור | שאלה | מחזיר |
|---|---|---|
| קטן מ | אמת / שקר |
| קטן או שווה | אמת / שקר |
| שווה | אמת / שקר |
| גדול או שווה | אמת / שקר |
| גדול מ | אמת / שקר |
| לא שווה | אמת / שקר |
| תלת־כיווני (sort) |
|
שני האופרנדים נכפים למחרוזות לפני ההשוואה.
$name eq "John" # exact string match
$kind ne "guest" # negated match
$word lt "m" # alphabetically before "m"
$a cmp $b # sort comparator
סדר לקסיקוגרפי#
מחרוזות מושוות תו אחר תו, נקודת־קוד אחר נקודת־קוד. התו הראשון השונה מכריע; אם מחרוזת אחת היא קידומת של האחרת, הקצרה מנצחת.
"abc" lt "abd" # TRUE -- 'c' < 'd' at position 2
"abc" lt "abcd" # TRUE -- prefix loses
"ABC" lt "abc" # TRUE -- ASCII: uppercase < lowercase
"10" lt "9" # TRUE -- '1' < '9' at position 0 (lex, not numeric!)
הדוגמה האחרונה היא הסיבה הקנונית לקיומם של eq/lt/gt: כשאתם רוצים שמחרוזות־ספרות ימוינו מספרית, עליכם להשתמש ב־<=> או לכפות מראש.
יוניקוד#
סדר נקודות־קוד אינו זהה לסדר ה״אלפביתי״ המודע ל־locale:
"ä" gt "z"הוא TRUE תחת סדר נקודות־קוד מפני ש־U+00E4 מעבר ל־U+007A.תחת סדר DIN 5007-1 הגרמני (״מילוני״),
"ä"אמור להתמיין עם"a"- הרבה לפני"z".
לאיסוף (collation) נכון ל־locale, השתמשו ב־Unicode::Collate מ־perlfunc או ב־use locale עם locale מתאים. ה־lt/gt/cmp החשופים מעניקים לכם השוואה מסודרת, יציבה, בלתי־תלוית־שפה - שזה בדיוק הדבר הנכון עבור מפתחות sort, חלוקת האש לדליים, פלט בדיקה דטרמיניסטי, וכן הלאה. זהו הדבר הלא־נכון עבור רשימות אלפביתיות הפונות לבני־אדם בכל שפה שאינה אנגלית.
cmp למיון#
cmp הוא חללית השוואת־המחרוזות. הוא מחזיר -1, 0, או +1 ומשתרשר באותה דרך ש־<=> עושה:
my @sorted = sort { $a cmp $b } @names; # ascending lex order
my @cased = sort {
lc($a) cmp lc($b) || $a cmp $b # case-insensitive,
# ties broken by case
} @names;
ערבוב טעמים: באג מודגם#
ניב מיון מפתח־מורכב מהשוואה מספרית הראה שרשור־|| של <=> ו־cmp. הבאג שיש להימנע ממנו הוא שימוש באופרטור הלא־נכון עבור הטיפוס של המפתח:
# version strings like "1.10", "1.2", "1.20", ...
sort @versions # ASCII order: "1.10","1.2","1.20"
sort { $a <=> $b } @versions # numeric mash: works only by accident
# (everything past first dot ignored)
sort { sortkey($a) <=> sortkey($b) } @versions # parse first, then compare
התשובה הנכונה למחרוזות גרסה היא מפענח כמו Sort::Versions או טוקניזציית (\d+) בכתיבה עצמית; לא cmp ולא <=> עושים זאת נכון בעצמם.
קדימות#
השוואת מחרוזות חולקת את שורה 11 בטבלת הקדימות עם השוואה מספרית. הם לא־אסוציאטיביים - אזהרת השרשור מהשוואה מספרית חלה גם כאן:
"a" lt "b" lt "c" # parses as ("a" lt "b") lt "c"
# = 1 lt "c"
# = TRUE (because "1" < "c" lexically)
# - accidentally right for the wrong reason.
כתבו את הקוניונקציה במפורש עם &&.
ראו גם#
השוואה מספרית - המשפחה המקבילה.
-
perlfunc tools that pair with string comparison.
Unicode ב־Perl - ההבחנה בין locale לבין סדר־נקודות־קוד לעומק.