فصل ۹: لیستهای تو در تو (Nested Lists) در پایتون و کاربردهای آنها

مقدمه
در زبان برنامهنویسی پایتون، لیستها به عنوان یکی از پایهایترین و قدرتمندترین ساختارهای داده برای ذخیره و مدیریت مجموعهای از دادهها به کار میروند. اما زمانی که نیاز به ذخیرهسازی دادههای چندبعدی، دادههای ساختاریافته یا ماتریسها داریم، لیستهای معمولی پاسخگو نیستند. اینجاست که لیستهای تو در تو (Nested Lists) وارد بازی میشوند و امکان مدیریت لیستهایی از لیستها را در ابعادی فراتر از یک بعد فراهم میکنند.
۹.۱ | تعریف لیستهای تو در تو
لیست تو در تو چیست؟
لیست تو در تو در پایتون به لیستی گفته میشود که عناصر آن میتوانند خودشان لیستهای دیگری باشند. به زبان ساده، یک آرایه چندبعدی است که هر بعد میتواند یک مجموعه مجزا از دادهها را نگهداری کند. این قابلیت، مدیریت دادههای پیچیده مثل ماتریسهای عددی یا دادههای جدولی را فوقالعاده آسان میکند.
مزایا و ویژگیها
- ذخیرهسازی دادهها به صورت چند بعدی (مانند ماتریس یا آرایههای چندبعدی).
- در هر زیرلیست امکان تعریف نوع داده متفاوت و طول متفاوت وجود دارد.
- مناسب برای پیادهسازی دادههای ساختاریافته، نگاشت دادههای جدولی، صفحه بازی و غیره.
مثال ساده:
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
در این مثال، هر عضو matrix یک لیست است (در اینجا، سه ردیف با سه ستون). این ساختار برای پردازش ماتریسها و دادههای دو بعدی فوقالعاده مناسب است.
۹.۲ | دسترسی به عناصر لیستهای تو در تو
برای دسترسی به عناصر لیستهای تو در تو باید از چندین ایندکس استفاده کنید. هر ایندکس، سطح خاصی از عمق را مشخص میکند.
ساختار دسترسی
فرمول کلی:
element = list_name[ایندکس_خارجی][ایندکس_داخلی]
- ایندکس اول: شماره ردیف یا زیرلیست را مشخص میکند.
- ایندکس دوم: شماره عنصر داخل زیرلیست را مشخص میکند.
مثال:
print(matrix[0][0]) # خروجی: 1 → ردیف اول، ستون اول
print(matrix[1][2]) # خروجی: 6 → ردیف دوم، ستون سوم
print(matrix[2][1]) # خروجی: 8 → ردیف سوم، ستون دوم
توجه: هرگاه تعداد عناصر زیرلیستها متفاوت باشد، امکان تولید خطای IndexError در صورت دسترسی به خانهای که وجود ندارد، وجود خواهد داشت.
دسترسی و تغییر عنصر:
matrix[0][1] = 20
print(matrix)
# خروجی: [[1, 20, 3], [4, 5, 6], [7, 8, 9]]
۹.۳ | پیمایش و کار با لیستهای تو در تو
پرکاربردترین روش برای پیمایش لیستهای تو در تو، استفاده از حلقههای تودرتو (Nested Loops) است.
پیمایش با دو حلقه for تو در تو:
for row in matrix:
for element in row:
print(element, end=" ")
print() # رفتن به خط بعدی بعد از هر ردیف
خروجی:
1 2 3
4 5 6
7 8 9
پیمایش بر اساس ایندکس (دسترسی پیشرفتهتر)
for i in range(len(matrix)):
for j in range(len(matrix[i])):
print(f"مقدار در [{i}][{j}]:", matrix[i][j])
پیمایش در لیستهای ناهمگون (زیرلیستهای با طول متغیر)
var_lists = [[1, 2], [3, 4, 5], [6]]
for row in var_lists:
for val in row:
print(val, end=" ")
print() # خروجی: 1 2 3 4 5 6
۹.۴ | کاربردهای عملی لیستهای تو در تو در پایتون
لیستهای تو در تو یکی از عملیات پرمصرف در برنامهنویسی روزمره هستند. در ادامه برخی از کاربردهای کاربردی و واقعی آنها در دنیای برنامهنویسی را بررسی میکنیم.
۱. ماتریسها و عملیات ریاضی
ماتریسها ساختاری بسیار مهم در علوم داده، یادگیری ماشین، تصویربرداری دیجیتال و دهها حوزه دیگر هستند. لیستهای تو در تو طراحی مناسبی برای نمایش و عملیات بر روی ماتریسها فراهم میکنند.
مثال: ترانهاده (Transpose) یک ماتریس
matrix = [
[1, 2, 3],
[4, 5, 6]
]
transpose = [[0 for _ in range(len(matrix))] for _ in range(len(matrix[0]))]
for i in range(len(matrix)):
for j in range(len(matrix[0])):
transpose[j][i] = matrix[i][j]
for row in transpose:
print(row)
خروجی:
[1, 4]
[2, 5]
[3, 6]
یکی دیگر از کاربردهای رایج: جمع و ضرب ماتریسها.
مثال: جمع دو ماتریس
A = [
[1, 2],
[3, 4]
]
B = [
[5, 6],
[7, 8]
]
result = [[A[i][j] + B[i][j] for j in range(len(A[0]))] for i in range(len(A))]
print(result) # خروجی: [[6, 8], [10, 12]]
۲. ذخیره و پردازش دادههای جدولی (Data Table)
لیستهای تو در تو بهترین گزینه برای مدیریت دادههای جدولی هستند: مانند ردیفهای دیتابیس یا دادههای فایل CSV.
مثال:
data = [
["نام", "سن", "شهر"],
["علی", 25, "تهران"],
["رضا", 30, "اصفهان"],
["مریم", 22, "شیراز"]
]
for row in data:
print(row[0], row[1], row[2])
خروجی:
نام سن شهر
علی 25 تهران
رضا 30 اصفهان
مریم 22 شیراز
۳. نمایش صفحه بازی (گیم بورد)
در بسیاری از بازیهای رایانه، جدول وضعیت صفحه بازی با لیستهای تو در تو مدلسازی میشود (شطرنج، تختهنرد، مار و پله و غیره).
مثال: صفحه شطرنج
board = [
["R", "N", "B", "Q", "K", "B", "N", "R"],
["P", "P", "P", "P", "P", "P", "P", "P"],
[" ", " ", " ", " ", " ", " ", " ", " "],
[" ", " ", " ", " ", " ", " ", " ", " "],
[" ", " ", " ", " ", " ", " ", " ", " "],
[" ", " ", " ", " ", " ", " ", " ", " "],
["p", "p", "p", "p", "p", "p", "p", "p"],
["r", "n", "b", "q", "k", "b", "n", "r"]
]
for row in board:
print(" ".join(row))
خروجی:
R N B Q K B N R
P P P P P P P P
p p p p p p p p
r n b q k b n r
۴. ذخیره گرافها و شبکهها (Adjacency Matrix)
در مباحث شبکه و الگوریتمهای گراف، لیست تو در تو برای نمایش اتصال گرهها کاربرد دارد.
# ماتریس مجاورت برای گرافی با ۳ گره
adjacency = [
[0, 1, 0],
[1, 0, 1],
[0, 1, 0]
]
۹.۵ | نکات تکمیلی و حرفهای درباره لیستهای تو در تو
مدیریت لیستهای نامتقارن
در پایتون، زیرلیستها (ردیفها) مجبور نیستند همگی به یک اندازه باشند:
nested = [[1, 2], [3, 4, 5], [6]]
# پیمایش ایمن:
for row in nested:
for el in row:
print(el)
ایجاد لیست تو در تو به روش لیست کامپرهنشن
# ایجاد ماتریس صفر ۳×۴
matrix = [[0 for _ in range(4)] for _ in range(3)]
print(matrix)
کپی عمیق (Deep Copy) vs کپی سطحی
کپی مستقیم یک لیست تو در تو، فقط مرجع به زیرلیستها را کپی میکند. برای کپی مستقل همه محتوا باید از copy.deepcopy استفاده کنید:
import copy
original = [[1,2],[3,4]]
clone = copy.deepcopy(original)
clone[0][0] = 99
print(original) # تغییر نمیکند!
جستجو در لیستهای تو در تو
target = 5
found = any(target in row for row in matrix)
تبدیل لیست تو در تو به لیست یکبعدی (Flattenting)
flat = [el for row in matrix for el in row]
۹.۶ | چالشها، اشتباهات رایج و عیبیابی
۱. اشتباه در نوشتن ایندکس
فراموشی ترتیب صحیح ایندکس میتواند منجر به IndexError شود.
matrix[3][0] # اگر فقط سه ردیف داشته باشیم، خطا میدهد
۲. انتظار طول یکسان زیرلیستها
فرض اینکه همه ردیفها طول مساوی دارند اشتباه است. همیشه قبل از دسترسی به ایندکس، طول زیرلیست را بسنجید.
۳. کپی نادرست در لیستهای تو در تو
کپی فقط با new_list = old_list[:] کافی نیست و باعث اشتراک مرجع زیرلیستها میشود. باید از کپی عمیق استفاده کنید.
۹.۷ | پرسشهای پر تکرار (FAQ) درباره لیستهای تو در تو
۱. آیا میتوان بیش از دو سطح لیست تو در تو داشت؟
بله؛ لیستها میتوانند چندین سطح تو در تو داشته باشند (سهبعدی، چهار بعدی و …).
۲. تفاوت لیست تو در تو و آرایه چندبعدی چیست؟
در پایتون، آرایههای چند بعدی واقعی را باید با کتابخانههایی نظیر NumPy ساخت؛ لیست تو در تو انعطاف بیشتری دارد ولی فاقد عملکرد ریاضی بهینه است.
۳. چطور لیست تو در تو را از کاربر دریافت کنیم؟
میتوانید با حلقه و input به تدریج داده را از کاربر گرفته و append کنید.
۴. چطور تمام عناصر لیست تو در تو را یکجا و بدون حلقه تو در تو چاپ کنیم؟
میتوانید با فشردهسازی (Flatten) و استفاده از join این کار را انجام دهید.
۹.۸ | تمرینها و مسائل کاربردی
تمرین ۱: مجموع عناصر یک لیست تو در تو
یک برنامه بنویسید که یک لیست تو در تو از اعداد را دریافت کند و مجموع همه عناصر را محاسبه کند.
پاسخ:
numbers = [
[1, 2, 3],
[4, 5],
[6]
]
total = 0
for row in numbers:
for num in row:
total += num
print("مجموع اعداد:", total)
تمرین ۲: پیدا کردن طولانیترین رشته در لیست تو در تو
یک برنامه بنویسید که یک لیست تو در تو از رشتهها را دریافت کند و طولانیترین رشته را پیدا کند و چاپ کند.
پاسخ:
words = [
["علی", "رضا", "سارا"],
["محمد", "شیوا"],
["نازنین", "امیرعباس", "ندا"]
]
longest = ""
for row in words:
for word in row:
if len(word) > len(longest):
longest = word
print("طولانیترین رشته:", longest)
تمرین ۳: تبدیل لیست تو در تو به لیست یکبعدی
لیست تو در تو [[1,2,3],[4,5],[6,7,8,9]] را به لیست [1,2,3,4,5,6,7,8,9] تبدیل کنید.
پاسخ:
nested = [[1,2,3],[4,5],[6,7,8,9]]
flattened = [item for sublist in nested for item in sublist]
print(flattened)
تمرین ۴: ساخت جدول ضرب با لیست تو در تو
جدول ضرب ۱ تا ۵ را در قالب لیست تو در تو بسازید و چاپ کنید.
پاسخ:
table = [[i*j for j in range(1,6)] for i in range(1,6)]
for row in table:
print(row)
جمعبندی فصل ۹
لیستهای تو در تو ابزاری انعطافپذیر و قدرتمند برای مدیریت دادههای ساختاریافته، جدولی و چندبعدی هستند. برای تحلیل دادههای آماری، پردازش تصویر، پیادهسازی بازیها، ماتریسهای ریاضی و دهها کاربرد دیگر جایگاه ویژهای دارند و یادگیری کاملشان مسیر حرفهای شدن در پایتون را هموار میکند.