به‌کارگیری حلقه‌ی while در لیست‌ها و دیکشنری‌ها

تا اینجا هر بار تنها با یک مورد از اطّلاعات کاربر سر و کار داشته‌ایم. ورودی را از کاربر گرفته و همان را یا پاسخی به آن را چاپ کرده‌ایم. پس از آن در یک حلقه‌ی while مقدار ورودیِ دیگری را گرفتیم و به آن پاسخ دادیم. امّا برای نگه‌داری و پیگیری کاربران بیشتر یا اطّلاعات پرتعدادتر در حلقه‌های while، به لیست‌ها و دیکشنری‌ها احتیاج داریم.

به‌کارگیری یک حلقه‌ی for برای حلقه زدن در یک لیست موثّر است امّا نباید لیست را در داخل این حلقه تغییر داد چون پایتون در پیگیری موارد داخل لیست دچار مشکل می‌شود. اگر می‌خواهید هنگام کار کردن با یک لیست آن را تغییر دهید، از حلقه‌ی while استفاده کنید.

انتقال دادن اعضا از یک لیست به لیستِ دیگر

لیستی از کاربران تازه ثبت‌نام شده‌ی یک وب‌سایت را در نظر بگیرید که هنوز تایید نشده‌اند. چگونه می‌توانیم پس از تایید این کاربران، آن‌ها را به لیستی مجزّا شامل کاربران تاییدشده منتقل کنیم؟ یک روش استفاده کردن از حلقه‌ی while است تا به کمک آن کاربران را از لیست کاربران تاییدنشده بیرون بکشیم، تایید کنیم و سپس به لیستی جداگانه از کاربران تاییدشده اضافه کنیم:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# Start with users that need to be verified,
# and an empty list to hold confirmed users.
unconfirmed_users = ['alice', 'brian', 'candace']
confirmed_users = []

# Verify each user until there are no more unconfirmed users.
# Move each verified user into the list of confirmed users.
while unconfirmed_users:
    current_user = unconfirmed_users.pop()

    print(f"Verifying user: {current_user.title()}")
    confirmed_users.append(current_user)

# Display all confirmed users.
print("\nThe following users have been confirmed:")
for confirmed_user in confirmed_users:
    print(confirmed_user.title())

در 1 با لیستِ کاربرانِ تاییدنشده (Alice، Brian و Candace) و لیستی خالی برای نگهداری کاربران تاییدشده شروع می‌کنیم. حلقه‌ی while در 2 تا زمانی که لیست unconfirmed_users خالی نباشد به کار ادامه می‌دهد. داخل این حلقه و در 3، تابع pop() هر بار کاربران تاییدنشده را از انتهای unconfirmed_users برمی‌دارد. اینجا چون Candace آخرین کاربر در unconfirmed_users است، نامش اوّلین نامی خواهد بود که از لیست حذف، به متغیّر current_user منسوب و به لیست confirmed_users اضافه می‌شود (4). بعدی Brian و سپس Alice خواهد بود.

فرآیند تایید کاربران را با چاپ کردن یک پیام تایید شبیه‌سازی می‌کنیم و سپس کاربران را به لیست تاییدشده‌ها می‌افزاییم. همزمان با کوچک شدن لیست کاربران تاییدنشده، لیست تایید‌شده‌ها بزرگ‌تر می‌شود:

1
2
3
4
5
6
7
8
Verifying user: Candace
Verifying user: Brian
Verifying user: Alice

The following users have been confirmed:
Candace
Brian
Alice

حذف کردن مقدارهای مشخّصی از یک لیست

در فصل ۳ از remove() برای حذف کردن یک مقدار مشخّص از لیست استفاده کردیم. این تابع به این دلیل کار می‌کرد که مقدار مورد نظر ما تنها یک بار در لیست ظاهر شده بود. امّا اگر بخواهیم تمام نمونه‌های یک مقدار را از لیستی حذف کنیم، چه؟

فرض کنید لیستی از حیوانات خانگی دارید که ‘cat’ در آن بارها تکرار شده است. برای حذف تمام مشابه‌های این مقدار می‌توانید یک حلقه‌ی while را تا زمانی اجرا کنید که هیچ موردی از ‘cat’ در لیست باقی نمانده باشد:

1
2
3
4
5
6
7
8
pets = ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']

print(pets)

while 'cat' in pets:
    pets.remove('cat')

print(pets)

با لیستی شامل چند عضو مشابه ‘cat’ شروع می‌کنیم. پس از چاپ کردن این لیست، پایتون وارد حلقه‌ی while می‌شود زیرا مقدار ‘cat’ را دستِ کم یک بار در لیست می‌یابد. پس از ورود به حلقه، پایتون اوّلین نمونه‌ی ‘cat’ را حذف کرده و به خطّ while برمی‌گردد. سپس از آن‌جا که هنوز ‘cat’ در لیست وجود دارد، مجدّداً وارد حلقه می‌شود. تا زمانی که دیگر هیچ مقداری مشابه ‘cat’ در حلقه موجود نباشد، هر نمونه‌ی آن را حذف می‌کند:

1
2
3
['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']

['dog', 'dog', 'goldfish', 'rabbit']

پر کردن یک دیکشنری با ورودی کاربر

در هر مرحله‌ی اجرای حلقه‌ی while، می‌توانید هرقدر اطّلاعات که بخواهید دریافت کنید. بیایید یک برنامه‌ی نظرسنجی بسازیم که در آن در هر بار اجرای حلقه یک بار نام و نظر مشارکت‌کنندگان را می‌پرسیم. داده‌های گردآوری‌شده را در یک دیکشنری ذخیره می‌کنیم زیرا می‌خواهیم بین هر کاربر و پاسخ او ارتباط برقرار کنیم:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
responses = {}

# Set a flag to indicate that polling is active.
polling_active = True

while polling_active:
    # Prompt for the person's name and response.
    name = input("\nWhat is your name? ")
    response = input("Which mountain would you like to climb someday? ")

    # Store the response in the dictionary.
    responses[name] = response

    # Find out if anyone else is going to take the poll.
    repeat = input("Would you like to let another person respond? (yes/ no) ")

    if repeat == 'no':
        polling_active = False

# Polling is complete. Show the results.
print("\n--- Poll Results ---")
for name, response in responses.items():
    print(f"{name} would like to climb {response}.")

این برنامه ابتدا یک دیکشنری خالی (responses) تعریف می‌کند و پرچمی (polling_active) را برای نمایش فعّال بودن نظرسنجی مقداردهی می‌کند. تا زمانی که polling_active برابر با True باشد، پایتون کد داخل حلقه‌ی while را اجرا می‌کند.

در داخل حلقه به کاربر اعلام می‌شود که نام و کوه مورد علاقه‌ی خود برای نوردیدن را وارد کند. این اطّلاعات در دیکشنری responses ذخیره می‌شود و از کاربر پرسیده می‌شود که آیا نظرسنجی ادامه یابد یا نه. اگر yes وارد شود، برنامه بار دیگر وارد حلقه‌ی while می‌شود. اگر no وارد شود پرچم polling_active به False تغییر می‌یابد و اجرای حلقه‌ی while متوقّف می‌شود. سرانجام بخش آخر کد نتایج نظرسنجی را نشان می‌دهد.

اگر برنامه را اجرا کرده و چند پاسخ نمونه وارد کنید، باید خروجی‌ای مانند زیر ببینید:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
What is your name? Eric
Which mountain would you like to climb someday? Denali
Would you like to let another person respond? (yes/ no) yes

What is your name? Lynn
Which mountain would you like to climb someday? Devil's Thumb
Would you like to let another person respond? (yes/ no) no

--- Poll Results ---
Lynn would like to climb Devil's Thumb.
Eric would like to climb Denali.

خودآزمایی

غذافروشی

لیستی به نام sandwich_orders بسازید و آن را با نام چند نوع ساندویچ پر کنید. سپس لیستی خالی به نام finished_sandwiches بسازید. در لیست سفارش‌های ساندویچ حلقه بزنید و برای هر کدام پیامی چاپ کنید، مثلاً I made your tuna sandwich.. با درست شدن هر ساندویچ، سفارش آن را به لیست‌های ساندویچ‌های تحویل‌داده‌شده منتقل کنید. پس از آماده شدن تمام ساندویچ‌ها پیامی چاپ کنید و تمام ساندویچ‌های آماده‌شده را فهرست کنید.

تمام شدنِ پاسترامی

لیستِ sandwich_orders در تمرین ۷-۸ را دوباره به کار بگیرید و مطمئن شوید ساندویچ ‘pastrami’ دستِ کم ۳ بار در آن تکرار شده باشد. در ابتدای برنامه‌ی خود پیامی چاپ کنید حاکی از آن‌که موجودیِ پاسترامی در این غذاخوری به پایان رسیده است، سپس به کمک یک حلقه‌ی while تمام موارد ‘pastrami’ را از sandwich_orders حذف کنید. مطمئن شوید که در لیست ساندویچ‌های آماده هیچ نمونه‌ای از ساندویچ پاسترامی نباشد.

سفر رویایی

برنامه‌ای بنویسید که از کاربران درباره‌ی سفر رویایی آن‌ها نظرسنجی کند. اعلانی مانند این چاپ کنید: If you could visit one place in the world, where would you go?. بخشی از کد را به چاپ کردن نتایج نظرسنجی اختصاص دهید.