אופרטורי השוואת מחרוזות#

המקבילות בטעם־מחרוזת של משפחת ההשוואה המספרית. אותה צורה, אותה שורת קדימות, אך פועלות לקסיקוגרפית (סדר נקודות־קוד של Unicode בברירת מחדל) במקום מספרית.

אופרטור

שאלה

מחזיר

lt

קטן מ

אמת / שקר

le

קטן או שווה

אמת / שקר

eq

שווה

אמת / שקר

ge

גדול או שווה

אמת / שקר

gt

גדול מ

אמת / שקר

ne

לא שווה

אמת / שקר

cmp

תלת־כיווני (sort)

-1, 0, או +1

שני האופרנדים נכפים למחרוזות לפני ההשוואה.

$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.

כתבו את הקוניונקציה במפורש עם &&.

ראו גם#