درس ۱۲ از ۴۹ · داده‌ها و گونه‌ها

آرایه‌ها و برش‌ها

آرایه تعداد ثابتی مقدار هم‌گونه را پشت‌سرهم نگه می‌دارد و با شماره (اندیس) به هر کدام دسترسی دارید. آرایه ساده‌ترین و سریع‌ترین راه نگه‌داشتن فهرستی است که طولش را از پیش می‌دانید.

ساختن و خواندن آرایه

آرایه را با کروشه بسازید. شماره‌ی عضوها از صفر شروع می‌شود و طول() تعداد عضوها را می‌دهد. برای تغییر عضوها، آرایه را ناپایا تعریف کنید. سرچاپ کل آرایه را یک‌جا چاپ می‌کند و عضوهای یک آرایه می‌توانند خودشان آرایه باشند، مثل جدول در این مثال.

arr-basics.salam
تابع ریشه:
    ناپایا عددها := [۵، ۳، ۸، ۱]
    سرچاپ عددها[۰]، عددها[۳]، طول(عددها)
    عددها[۱] = ۹۰
    سرچاپ عددها
    جدول := [[۱، ۲، ۳]، [۴، ۵، ۶]]
    سرچاپ جدول[۱][۲]
پایان
خروجی5 1 4 [5, 90, 8, 1] 6

گونه‌ی عددها صحیح[۴] است: طول بخشی از گونه است و هرگز عوض نمی‌شود. اگر فهرستی لازم دارید که بزرگ شود، از وکتور در درس مجموعه‌ها استفاده کنید.

آرایه با اندازه‌ی معین

وقتی طول را می‌دانید ولی هنوز مقدارها را نه، آرایه را با گونه‌اش تعریف کنید: ناپایا رای‌ها: صحیح[۴]. عضوهای عددی از صفر و عضوهای منطقی از نادرست شروع می‌شوند. شمردن چیزها بر اساس شماره‌شان کاربرد معروف این شکل است:

arr-sized.salam
تابع ریشه:
    ناپایا رای‌ها: صحیح[۴]
    برگه‌ها := [۲، ۰، ۲، ۳، ۲، ۰]
    هر ب در برگه‌ها:
        رای‌ها[ب]++
    پایان
    سرچاپ رای‌ها
    هر گزینه، شمار در رای‌ها:
        سرچاپ "گزینه‌ی"، گزینه، "رای:"، شمار
    پایان
پایان
خروجی[2, 0, 3, 1] گزینه‌ی 0 رای: 2 گزینه‌ی 1 رای: 0 گزینه‌ی 2 رای: 3 گزینه‌ی 3 رای: 1

عضوهای آرایه‌ی رشته‌ای را که این‌طور تعریف شده، پیش از مقدار دادن نخوانید: هنوز هیچ رشته‌ای در آن‌ها نیست و خواندنشان برنامه را از کار می‌اندازد. آرایه‌ی رشته را با یک مقدار آغازین بسازید، مثل [""، ""، ""].

پیمایش آرایه

هر عضو در آرایه عضوها را به ترتیب می‌پیماید. با دو نام، هر ش، عضو در آرایه، جایگاه هر عضو را هم می‌گیرید.

arrays.salam
تابع ریشه:
    میوه‌ها := ["سیب", "انار", "انگور"]
    هر میوه در میوه‌ها:
        سرچاپ "من", میوه, "دوست دارم"
    پایان
    سرچاپ "تعداد:", میوه‌ها.طول()
پایان
خروجیمن سیب دوست دارم من انار دوست دارم من انگور دوست دارم تعداد: 3

بیشتر کارها روی آرایه یک حلقه است که نتیجه‌ای را با خودش جلو می‌برد: جمع تا این‌جا، جایگاه بزرگ‌ترین عضو تا این‌جا، یا نخستین جایگاهی که می‌خواهیم. اگر هم جایگاه و هم مقدار را لازم دارید، جایگاه را نگه دارید، مثل پرباران در مثال پایین. تابع جستجو وقتی چیزی پیدا نکند -۱ برمی‌گرداند، عددی که نمی‌تواند جایگاه واقعی باشد.

arr-stats.salam
تابع جایگاه(فهرست: رشته[]، خواسته: رشته): صحیح:
    هر ش، عضو در فهرست:
        اگر عضو == خواسته:
            برگشت ش
        پایان
    پایان
    برگشت -۱
پایان

تابع ریشه:
    ماه‌ها := ["فروردین"، "اردیبهشت"، "خرداد"، "تیر"، "مرداد"، "شهریور"]
    باران := [۷۸، ۶۴، ۵۱، ۳۳، ۱۲، ۴]
    ناپایا مجموع := ۰
    ناپایا پرباران := ۰
    هر ش، م در باران:
        مجموع += م
        اگر م > باران[پرباران]:
            پرباران = ش
        پایان
    پایان
    سرچاپ "مجموع:"، مجموع، "میانگین:"، مجموع / طول(باران)
    سرچاپ "پرباران‌ترین:"، ماه‌ها[پرباران]، باران[پرباران]
    سرچاپ "تیر ماه شماره‌ی"، جایگاه(ماه‌ها، "تیر") + ۱
    سرچاپ "اسفند در جایگاه"، جایگاه(ماه‌ها، "اسفند")
پایان
خروجیمجموع: 242 میانگین: 40 پرباران‌ترین: فروردین 78 تیر ماه شماره‌ی 4 اسفند در جایگاه -1

دو آرایه با گونه‌ی عضو و طول یکسان را می‌شود با == و != مقایسه کرد: وقتی همه‌ی عضوهایشان برابر باشند برابرند، پس [۱، ۲، ۳] == [۱، ۲، ۳] مقدار درست دارد. آرایه‌هایی با طول متفاوت را نمی‌شود مقایسه کرد، و آرایه‌ها را با < یا > هم نمی‌شود سنجید؛ هر دو خطای E021 هستند.

آرایه‌ی دوبعدی

آرایه‌ای از آرایه‌ها یک جدول است: فروش[ر][س] یعنی ردیف ر و ستون س. طول(فروش) تعداد ردیف‌ها و طول(فروش[۰]) تعداد ستون‌هاست. آرایه را می‌شود در چند خط نوشت تا جدول خوانا بماند. هر آرایه‌ی دوبعدی را نمی‌پیماید (E065)، پس از تکرار با اندیس استفاده کنید. یک ردیف، یعنی فروش[ر]، آرایه‌ای معمولی است و می‌شود آن را به تابع داد.

arr-grid.salam
تابع جمع کل(مقدارها: صحیح[]): صحیح:
    ناپایا جمع := ۰
    هر ع در مقدارها:
        جمع += ع
    پایان
    برگشت جمع
پایان

تابع ریشه:
    فروش := [
        [۱۲، ۷، ۳، ۹]،
        [۵، ۱۱، ۸، ۶]،
        [۹، ۴، ۱۰، ۲]
    ]
    شعبه‌ها := ["شمال"، "جنوب"، "شرق"]
    تکرار طول(فروش) در ر:
        سرچاپ شعبه‌ها[ر]، جمع کل(فروش[ر])
    پایان
    ناپایا روزها := ""
    تکرار طول(فروش[۰]) در س:
        ناپایا جمع := ۰
        تکرار طول(فروش) در ر:
            جمع += فروش[ر][س]
        پایان
        روزها += " " + جمع
    پایان
    سرچاپ "هر روز:" + روزها
پایان
خروجیشمال 31 جنوب 30 شرق 25 هر روز: 26 22 21 17

برای تعریف جدول خالی، هر دو اندازه را بنویسید: ناپایا شبکه: صحیح[۳][۴].

آرایه مقدار است

نسبت دادن آرایه به متغیری دیگر همه‌ی آن را کپی می‌کند. فرستادن آن به ورودی‌ای با اندازه‌ی معین مثل صحیح[۳] و برگرداندنش از تابع هم همین‌طور. تغییر دادن کپی هیچ‌وقت به اصل دست نمی‌زند.

arr-copy.salam
تابع با جایزه(نمره‌ها: صحیح[۳]): صحیح[۳]:
    ناپایا خروجی := نمره‌ها
    تکرار طول(خروجی) در ش:
        خروجی[ش] += ۵
    پایان
    برگشت خروجی
پایان

تابع ریشه:
    اصلی := [۷۰، ۸۵، ۹۰]
    ناپایا پیش‌نویس := اصلی
    پیش‌نویس[۰] = ۰
    سرچاپ اصلی، پیش‌نویس
    ارفاقی := با جایزه(اصلی)
    سرچاپ اصلی، ارفاقی
پایان
خروجی[70, 85, 90] [0, 85, 90] [70, 85, 90] [75, 90, 95]

این باعث می‌شود جابه‌جا کردن آرایه بی‌خطر باشد، ولی کپی کردن آرایه‌ی بزرگ در هر فراخوانی وقت می‌گیرد. وقتی تابع فقط باید آرایه را بخواند، یا باید آرایه‌ی فراخواننده را تغییر دهد، به آن برش بدهید.

برش

آرایه[آغاز: پایان] برشی از آرایه می‌سازد که عضوهای آغاز تا پیش از پایان را نشان می‌دهد؛ کپی نیست و به همان داده اشاره می‌کند. [: ۲] از ابتدا و [۴:] تا انتها را می‌گیرد. ورودی‌ای با گونه‌ی صحیح[] هر آرایه یا برشی از صحیح‌ها را با هر طولی می‌پذیرد و آرایه را هم می‌شود مستقیم و بدون کپی به آن داد.

arr-slices.salam
تابع جمع(نما: صحیح[]): صحیح:
    ناپایا مجموع := ۰
    هر ع در نما:
        مجموع += ع
    پایان
    برگشت مجموع
پایان

تابع ریشه:
    داده := [۱، ۲، ۳، ۴، ۵، ۶]
    میانه := داده[۱: ۴]
    سرچاپ طول(میانه)، جمع(میانه)
    سرچاپ جمع(داده)، جمع(داده[: ۲])، جمع(داده[۴:])
پایان
خروجی3 9 21 3 11

برش در آرایه می‌نویسد

چون برش به داده‌ی فراخواننده اشاره می‌کند، تابعی که عضوهای ورودی صحیح[] را تغییر دهد، آرایه‌ی فراخواننده را تغییر می‌دهد. اگر برشی از بخشی از آرایه بفرستید، فقط همان بخش عوض می‌شود.

arr-slice-write.salam
تابع تخفیف(بهاها: صحیح[]، درصد: صحیح):
    تکرار طول(بهاها) در ش:
        بهاها[ش] -= بهاها[ش] * درصد / ۱۰۰
    پایان
پایان

تابع ریشه:
    ناپایا بهاها := [۲۰۰، ۱۵۰، ۸۰، ۶۰، ۴۰]
    تخفیف(بهاها[۳:]، ۵۰)
    سرچاپ بهاها
    تخفیف(بهاها، ۱۰)
    سرچاپ بهاها
پایان
خروجی[200, 150, 80, 30, 20] [180, 135, 72, 27, 18]

تابع نباید برشی از آرایه‌ی محلی خودش را برگرداند، چون آن آرایه پس از برگشتن تابع از بین می‌رود؛ مترجم این را نمی‌پذیرد (E012).

خطای اندیس

خواندن یا نوشتن بیرون از آرایه همیشه اشتباه است و سلام آن را می‌گیرد. اگر اندیس ثابت باشد، ساخت متوقف می‌شود: آ[۳] روی آرایه‌ای سه‌عضوی خطای «اندیس ۳ برای آرایه‌ای به طول ۳ خارج از محدوده است» (E168) می‌دهد. اگر اندیس فقط هنگام اجرا معلوم شود، برنامه با پیام array index 5 out of bounds [0,3) می‌ایستد و حافظه‌ای را که مال آرایه نیست نمی‌خواند.

ساخت با --release برای سرعت این سنجش‌های هنگام اجرا را کنار می‌گذارد و آن‌جا خطای اندیس دیگر گرفته نمی‌شود. اول بدون --release آزمایش کنید.

چند قاعده‌ی سرانگشتی

  • وقتی طول معلوم و ثابت است آرایه، و وقتی نیست وکتور به کار ببرید.
  • ورودی آرایه‌ای را صحیح[] (برش) بگیرید، مگر این‌که تابع کپی خودش را لازم داشته باشد.
  • یادتان باشد برش در آرایه‌ای که از آن آمده می‌نویسد.
  • آرایه‌ی دوبعدی را با تکرار و دو اندیس بپیمایید.
  • جستجویی که چیزی پیدا نمی‌کند -۱ برگرداند و فراخواننده آن را بررسی کند.