זוהי הפקודה perllol שניתן להריץ בספק האירוח החינמי של OnWorks באמצעות אחת מתחנות העבודה המקוונות החינמיות שלנו כגון Ubuntu Online, Fedora Online, אמולטור מקוון של Windows או אמולטור מקוון של MAC OS.
תָכְנִית:
שֵׁם
perllol - מניפולציה של מערכים של מערכים בפרל
תיאור
הכרזה ו גִישָׁה of מערכים of מערכים
מבנה הנתונים הדו-מפלסי הפשוט ביותר לבנייה בפרל הוא מערך של מערכים, לפעמים
נקרא כבדרך אגב רשימת רשימות. זה די קל להבנה, וכמעט
כל מה שמתאים כאן יהיה רלוונטי גם בהמשך עם הנתונים המעודכנים יותר.
מבנים.
מערך של מערך הוא סתם מערך רגיל @AoA שניתן להגיע אליו עם שניים
כתבי תחתיים, כמו $AoA[3][2]. הנה הצהרה של המערך:
השתמש ב-5.010; # כדי שנוכל להשתמש ב-say()
# להקצות למערך שלנו, מערך של הפניות למערך
@AoA = (
[ "פרד", "בארני", "חלוקי נחל", "במבם", "דינו", ],
[ "ג'ורג'", "ג'יין", "אלרוי", "ג'ודי", ],
[ "הומר", "בארט", "מארג", "מאגי", ],
);
נניח $AoA[2][1];
בארט
עכשיו עליכם להיזהר מאוד שסוג התושבת החיצונית הוא עגול, כלומר,
סוגריים. הסיבה לכך היא שאתה מקצה ל-@array, אז אתה צריך סוגריים. אם
רצית שם לֹא להיות @AoA, אלא רק התייחסות אליו, אתה יכול לעשות
משהו יותר כזה:
# הקצה הפניה למערך של הפניות למערך
$ref_to_AoA = [
[ "פרד", "בארני", "חלוקי נחל", "במבם", "דינו", ],
[ "ג'ורג'", "ג'יין", "אלרוי", "ג'ודי", ],
[ "הומר", "בארט", "מארג", "מאגי", ],
];
אמור $ref_to_AoA->[2][1];
בארט
שימו לב שסוג הסוגריים החיצוניים השתנה, ולכן גם תחביר הגישה שלנו השתנה.
הסיבה לכך היא שבניגוד ל-C, בפרל אי אפשר להחליף בחופשיות מערכים והפניות.
לכך. $ref_to_AoA הוא הפניה למערך, בעוד ש-@AoA הוא מערך עצמו.
באופן דומה, $AoA[2] אינו מערך, אלא הפניה למערך. אז איך זה שאפשר לכתוב את אלה:
$AoA[2][2]
$ref_to_AoA->[2][2]
במקום שיהיה צורך לכתוב את אלה:
$AoA[2]->[2]
$ref_to_AoA->[2]->[2]
ובכן, זה בגלל שהכלל הוא שרק בסוגריים סמוכים (בין אם מרובעים או מסולסלים),
אתה רשאי להשמיט את חץ הסרת ההפניה של המצביע. אבל אינך יכול לעשות זאת עבור ה...
הראשון אם זה סקלר המכיל הפניה, מה שאומר ש-$ref_to_AoA תמיד
צריך את זה.
גדל שלו
זה טוב ויפה להצהרה על מבנה נתונים קבוע, אבל מה אם תרצו
להוסיף אלמנטים חדשים תוך כדי תנועה, או לבנות את זה לגמרי מאפס?
ראשית, בואו נבחן קריאתו מקובץ. זה כמו הוספת שורה ב-
זמן. נניח שיש קובץ שטוח שבו כל שורה היא שורה וכל מילה היא
אלמנט. אם אתם מנסים לפתח מערך @AoA המכיל את כל אלה, הנה ההוראות הנכונות
דרך לעשות זאת:
בעוד (<>) {
@tmp = פיצול;
לדחוף את @AoA, [ @tmp ];
}
ייתכן שטענת את זה גם מפונקציה:
עבור $i ( 1 .. 10 ) {
$AoA[$i] = [ somefunc($i) ];
}
או שאולי היה לך משתנה זמני שנמצא יחד עם המערך בתוכו.
עבור $i ( 1 .. 10 ) {
@tmp = somefunc($i);
$AoA[$i] = [@tmp ];
}
חשוב לוודא שאתם משתמשים בבנאי ההפניות של המערך "[]". הסיבה לכך היא
זה לא יעבוד:
$AoA[$i] = @tmp; # טעות!
הסיבה שזה לא עושה את מה שאתה רוצה היא בגלל הקצאת מערך בעל שם כזה ל-
סקלר לוקח מערך בהקשר סקלר, מה שאומר שהוא סופר רק את מספר ה-
אלמנטים ב-@tmp.
אם אתם משתמשים תחת "use strict" (ואם לא, למה לעזאזל אתם לא משתמשים?),
תצטרך להוסיף כמה הצהרות כדי שזה יהיה מאושר:
השתמש מחמירים;
שלי (@AoA, @tmp);
בעוד (<>) {
@tmp = פיצול;
לדחוף את @AoA, [ @tmp ];
}
כמובן, אינך צריך כלל שלמערך הזמני יהיה שם:
בעוד (<>) {
push @AoA, [פיצול];
}
אתה גם לא חייב להשתמש לִדחוֹף()יכולת פשוט לבצע משימה ישירה אם ידעת
איפה שרצית לשים את זה:
שלי (@AoA, $i, $line);
עבור $i ( 0 .. 10 ) {
שורה $ = <>;
$AoA[$i] = [פיצול " ", $שורה];
}
או אפילו סתם
שלי (@AoA, $i);
עבור $i ( 0 .. 10 ) {
$AoA[$i] = [פיצול " ", <>];
}
באופן כללי עליך להיזהר משימוש בפונקציות שעלולות להחזיר רשימות ב
בהקשר סקלרי מבלי לציין זאת במפורש. זה יהיה ברור יותר למשתמש הרגיל
קוֹרֵא:
שלי (@AoA, $i);
עבור $i ( 0 .. 10 ) {
$AoA[$i] = [פיצול " ", סקלר(<>)];
}
אם תרצו להשתמש במשתנה $ref_to_AoA כהפניה למערך, תצטרכו לעשות זאת
משהו כזה:
בעוד (<>) {
דחיפה של @$ref_to_AoA, [פיצול];
}
כעת ניתן להוסיף שורות חדשות. מה לגבי הוספת עמודות חדשות? אם אתם מתמודדים עם...
מטריצות, לרוב הכי קל להשתמש בהקצאה פשוטה:
עבור $x (1 .. 10) {
עבור $y (1 .. 10) {
$AoA[$x][$y] = func($x, $y);
}
}
עבור $x (3, 7, 9) {
$AoA[$x][20] += פונקציה2($x);
}
לא משנה אם האלמנטים האלה כבר שם או לא: זה ייצור בשמחה
אותם עבורך, תוך הגדרת אלמנטים מתערבים ל"לא מוגדרים" לפי הצורך.
אם רצית רק להוסיף לשורה, תצטרך לעשות משהו שנראה קצת יותר מצחיק:
# הוספת עמודות חדשות לשורה קיימת
push @{ $AoA[0] }, "וילמה", "בטי"; # ביטול מפורש
לפני Perl 5.14, זה אפילו לא היה מתקמפל:
push $AoA[0], "wilma", "betty"; # הסרת קוד מרומזת
איך זה? כי פעם, הטיעון ל לִדחוֹף() היה צריך להיות מערך אמיתי, לא
רק התייחסות לאחד. זה כבר לא נכון. למעשה, השורה המסומנת "implicit deref"
הנ"ל עובד מצוין - במקרה הזה - כדי לעשות את מה שעשה זה שאומר deref מפורש.
הסיבה שאמרתי "במקרה הזה" היא בגלל ש... רק עובד כי $AoA[0] כבר
הכיל הפניה למערך. אם תנסה זאת על משתנה לא מוגדר, תקבל
יוצא מן הכלל. הסיבה לכך היא שההסרה המרומזת לעולם לא תהפוך אוטומטית לחיים של אובייקט לא מוגדר
משתנה כפי ש-"@{ }" תמיד יעשה:
ה-$aref שלי = undef;
דחיפה של $aref, qw(עוד כמה ערכים); # טעות!
לדחוף את @$aref, qw(עוד כמה); # בסדר
אם אתם רוצים לנצל את התנהגות ההפניה המרומזת החדשה הזו, המשיכו הלאה:
זה מקל על הקוד על העין ועל פרק כף היד. רק תבין שגרסאות ישנות יותר יחנקו.
עליו במהלך הקומפילציה. בכל פעם שאתה משתמש במשהו שעובד רק בחלק מסוים
בהינתן שחרור Perl ומאוחר יותר, אך לא מוקדם יותר, עליך למקם מקום בולט
השתמש בגרסה 5.14; # נדרש עבור deref מרומז של הפניות מערך על ידי פעולות מערך
ההוראה בראש הקובץ שזקוק לה. כך, כאשר מישהו מנסה להריץ את
קוד חדש תחת פרל ישן, במקום לקבל שגיאה כמו
סוג הארגומנט 1 לדחיפה חייב להיות מערך (לא אלמנט מערך) בשורה 8/tmp/a, ליד "betty";
ביצוע /tmp/a בוטל עקב שגיאות קומפילציה.
יודיעו להם בנימוס על כך
נדרשת Perl גרסה 5.14.0 - זוהי רק גרסה 5.12.3, נעצרת ב-/tmp/a שורה 1.
BEGIN נכשל -- הקומפילציה בוטלה בשורה 1 של /tmp/a.
גִישָׁה ו הדפסה
עכשיו הגיע הזמן להדפיס את מבנה הנתונים שלך. איך תעשה את זה? ובכן, אם
אם אתה רוצה רק אחד מהאלמנטים, זה טריוויאלי:
הדפס $AoA[0][0];
אם אתה רוצה להדפיס את הכל, אתה לא יכול להגיד
הדפס @AoA; # טעות
מכיוון שתקבלו רק הפניות ברשימה, ופרל לעולם לא תבצע ביטול הפניות אוטומטי
דברים בשבילך. במקום זאת, אתה צריך לגלגל לעצמך לולאה או שתיים. זה מדפיס את השלם
מבנה, באמצעות סגנון הקליפה ל() בנייה כדי ללולאה על פני הקבוצה החיצונית של
כתבי מנויים.
עבור $aref (@AoA) {
אמור "\t [ @$aref ],";
}
אם תרצו לעקוב אחר מנויים, תוכלו לעשות זאת כך:
עבור $i ( 0 .. $#AoA ) {
אמור "\t elt $i הוא [ @{$AoA[$i]} ],";
}
או אולי אפילו את זה. שימו לב ללולאה הפנימית.
עבור $i ( 0 .. $#AoA ) {
עבור $j ( 0 .. $#{$AoA[$i]} ) {
אמור "הערך $i $j הוא $AoA[$i][$j]";
}
}
כפי שאתם רואים, זה נהיה קצת מסובך. לכן לפעמים קל יותר לקחת
זמני בדרכך:
עבור $i ( 0 .. $#AoA ) {
$aref = $AoA[$i];
עבור $j ( 0 .. $#{$aref} ) {
אמור "הערך $i $j הוא $AoA[$i][$j]";
}
}
הממ... זה עדיין קצת מכוער. מה דעתך על זה:
עבור $i ( 0 .. $#AoA ) {
$aref = $AoA[$i];
$n = @$aref - 1;
עבור $j (0 .. $n) {
אמור "הערך $i $j הוא $AoA[$i][$j]";
}
}
כשאתה מתעייף מכתיבת הדפסה מותאמת אישית עבור מבני הנתונים שלך, אתה יכול להסתכל על
מודולי Dumpvalue או Data::Dumper הסטנדרטיים. הראשון הוא מה שבאגים של פרל
משתמש, בעוד שהאחרון מייצר קוד פרל הניתן לניתוח. לדוגמה:
להשתמש בגרסה 5.14; # משתמש ב- + אב טיפוס, חדש בגרסה 5.14
תוכנית משנה (+) {
דורשים ערך דומפ;
מצב $prettily = new Dumpvalue::
טיק => q("),
compactDump => 1, # להוציא את שתי השורות האלה מהתגובה
מאוד קומפקטי => 1, # אם אתה רוצה dump גדול יותר
;
dumpValue $יפהפה @_;
}
# הקצה רשימה של הפניות למערך למערך.
@AoA שלי = (
[ "פרד", "בארני" ],
[ "ג'ורג'", "ג'יין", "אלרוי" ],
[ "הומר", "מארג", "בארט" ],
);
לדחוף את $AoA[0], "וילמה", "בטי";
הצג @AoA;
ידפיס:
0 0..3 "פרד" "בארני" "וילמה" "בטי"
1 0..2 "ג'ורג'" "ג'יין" "אלרוי"
2 0..2 "הומר" "מרג'" "בארט"
בעוד שאם תסיר את שתי השורות שאמרתי שאולי תרצה, אז זה יראה לך את זה
בדרך זו במקום זאת:
0 מַעֲרָך(0x8031d0)
0 "פרד"
1 "בארני"
2 "וילמה"
3 "בטי"
1 מַעֲרָך(0x803d40)
0 "ג'ורג'"
1 "ג'יין"
2 "אלרוי"
2 מַעֲרָך(0x803e10)
0 "הומר"
1 "מרג'"
2 "בארט"
פרוסות
אם אתם רוצים להגיע לפלח (חלק משורה) במערך רב-ממדי, תצטרכו
צריך לעשות קצת יצירת מנוי מפוארת. זה בגלל שלמרות שיש לנו מילה נרדפת נחמדה ל
אלמנטים בודדים דרך חץ המצביע לצורך הסרת הפניות, נוחות כזו אינה קיימת עבור
פרוסות.
כך מבצעים פעולה אחת באמצעות לולאה. נניח משתנה @AoA כמו קודם.
@חלק = ();
$ x = 4;
עבור ($y = 7; $y < 13; $y++) {
דחיפה של @part, $AoA[$x][$y];
}
ניתן להחליף את אותה לולאה בפעולת פרוסה:
@part = @{$AoA[4]}[7..12];
או קצת מרווחים:
@part = @{ $AoA[4] } [ 7..12 ];
אבל כפי שאתם יכולים לתאר לעצמכם, זה יכול להיות די קשה עבור הקורא.
אה, אבל מה אם היית רוצה דו ממדי פרוסה, כמו למשל ש-$x יפעל מ-4..8 ו-$y
לרוץ מ-7 ל-12? הממ... הנה הדרך הפשוטה:
@newAoA = ();
עבור ($startx = $x = 4; $x <= 8; $x++) {
עבור ($starty = $y = 7; $y <= 12; $y++) {
$newAoA[$x - $startx][$y - $starty] = $AoA[$x][$y];
}
}
אנחנו יכולים להפחית חלק מהלולאות דרך פרוסות
עבור ($x = 4; $x <= 8; $x++) {
לדחוף את @newAoA, [ @{ $AoA[$x] } [ 7..12 ]];
}
אם היית מתעניין בטרנספורמציות שוורציאניות, כנראה שהיית בוחר במפה בשביל זה.
@newAoA = מפה { [ @{ $AoA[$_] } [ 7..12 ] ] } 4 .. 8;
למרות שאם המנהל שלך האשים אותך בחיפוש אחר ביטחון תעסוקתי (או חוסר ביטחון מהיר) באמצעות
קוד בלתי ניתן לפענוח, יהיה קשה להתווכח. :-) אם הייתי במקומך, הייתי שם את זה ב-
פוּנקצִיָה:
@newAoA = splice_2D( \@AoA, 4 => 8, 7 => 12);
תת-שזירה_2D {
ה-$lrr שלי = shift; # הפניה למערך של הפניות מערך!
שלי ($x_lo, $x_hi,
$y_lo, $y_hi) = @_;
מפת החזרה {
[ @{ $lrr->[$_] } [ $y_lo .. $y_hi ] ]
} $x_lo .. $x_hi;
}
השתמש בפרלול באופן מקוון באמצעות שירותי onworks.net