۹ - ۱۰فیلتر کردن لیست‌ها

در فصل ۷ که از ترکیبِ توابع صحبت کردیم، از تابعی به اسمِ ‏‎filter‎‏ گفتیم که یه لیستِ ورودی می‌گیره، و لیستی که برمی‌گردونه فقط حاوی مقادیری‌ه که شرط ِ تأمین شده رو ارضا می‌کنن. مثل بیانیه‌ی زیر که اعداد زوج ِ یک لیست رو پیدا می‌کنه و یه لیست جدید از اون مقادیر برمی‌گردونه:

Prelude> filter even [1..10]
[2,4,6,8,10]

‏‎filter‎‏ رو دقیق‌تر نگاه کنیم. این تعریفِ تابعِ ‏‎filter‎‏ ِه:

filter :: (a -> Bool) -> [a] -> [a]
filter _ []   = []
filter pred (x:xs)
  | pred x    = x : filter pred xs
  | otherwise = filter pred xs

‏‎filter‎‏ یه تابعی که ‏‎Bool‎‏ برمی‌گردونه رو روی یک لیست نگاشت میده، و یه لیستِ جدید با همه‌ی مقادیری که شرط براشون صادق بوده برمی‌گردونه. یک نکته‌ی مهم اینه که این تابع، همونطور که از تعریف‌ش پیداست، لیست ورودی رو تغییر نمیده، بلکه یه لیست جدید شامل مقادیری که شرط رو ارضا می‌کنن می‌سازه.

قبلاً دیدیم که ‏‎filter‎‏ با ‏‎odd‎‏ و ‏‎even‎‏ چطور کار می‌کنه. یک مثال هم شبیه این دیدیم:

Prelude> filter (== 'a') "abracadabra"
"aaaaa"

از آشنایی‌ای که با HOF ها پیدا کردیم، واضحه که ‏‎filter‎‏ انواع تایپ‌های ورودی رو قبول می‌کنه. مثال زیر معادلِ ‏‎filter even‎‏ عمل می‌کنه، اما با گرامر ِ تابع بی‌نام:

Prelude> filter (\x -> rem x 2 == 0) [1..20]
[2,4,6,8,10,12,14,16,18,20]

دیدیم که با لیست‌های توصیفی هم میشد لیست‌ها رو فیلتر کنیم. این دو تا رو مقایسه کنین:

relude> filter (\x -> elem x "aeiou") "abracadabra"
aaaaa"
relude> [x | x <- "abracadabra", elem x "aeiou"]
aaaaa"

هر راهی که دوست دارین انتخاب کنین.

باز هم پیشنهاد می‌کنیم با توابعِ دیگه ‏‎filter‎‏ رو امتحان کنین تا دست‌تون راه بیوفته.

تمرین‌ها: فیلترینگ

۱.

با توجه به مثال‌های بالا، چطور یه تابعِ فیلتر بنویسیم که مضرب‌های ۳ از یه لیستِ ۱ تا ۳۰ رو بهمون بده؟

۲.

با چیزهایی که از ترکیب توابع یاد گرفتیم، تابعِ تمرینِ قبل رو چطور با ‏‎length‎‏ ترکیب کنیم تا تعدادِ مضرب‌های ۳ بین ۱ تا ۳۰ رو پیدا کنیم؟

۳.

تابعی بنویسین که حروف تعریف (‏‎a‎‏، ‏‎an‎‏، و ‏‎the‎‏) رو از جمله‌ی ورودی حذف کنه. باید مثل این کار کنه:

Prelude> myFilter "the brown dog was a goof"
["brown","dog","was","goof"]

اگه به یاد داشته باشین، اوایلِ فصل تابعی ازتون خواستیم که یک نوشته رو با فاصله‌هاش تقسیم کنه و یه لیستِ نوشته برگردونه. این در واقع یکی از توابعِ کتابخونه ِ استاندارد به اسمِ ‏‎words‎‏ ِه. شاید خوب باشه این تمرین رو با ‏‎words‎‏ شروع کنین (یا اونی که خودتون نوشتین).