چگونه چندین عنصر بر اساس ایندکس حذف کنیم
۱۴۰۴/۱/۱۸ • ۱۵ دقیقه • عمومی
تا چند روز قبل به سفارش یکی از دوستان در حالا ساخت یک برنامه جدول بودم. در این برنامه ویژگی وجود داشت که اجازه میداد کاربر چندین سطر رو انتخاب کنه و دکمه حذف رو بزنه و سطرها حذف بشن.
اینکه این سطرها چطور حذف میشن یه این شکل بود که تمام سطرها در یک لیست ذخیره شده بودن. شماره سطر یا همون ایندکس سطری که توسط کاربر انتخاب شده بود هم در دسترس بود حالا کافی بود بر اساس این شماره سطرها از لیست سطرها سطرهای مورد نظر رو حذف کنیم. ولی یکی مشکلی بود فرض کنیم از بین پنج سطر موجود کاربر سطر اول و سطر پنجم رو انتخاب کرده تا حذف کنه. زمانی که سطر اول رو حذف کنیم دیگه اصلا سطر پنجمی نداریم که حذف بشه! چرا؟ چون یک سطر حذف شد و کلا چهار سطر مونده پس اگر دستور حذف بعدی ما این باشه که سطر پنجم رو حذف به خاطر نبود سطر پنجم با خطا مواجه خواهیم شد.
روش اول: کاهش ایندکس بعدی
در این روش هر بار که یک ایندکس حذف میکنیم ایندکس های بعدی که قرار حذف بر پایه اونها اتفاق بیفته رو یه دونه کم کنیم به این شکل:
a = ["moz", "qarpoz", "portakhal", "alma", "qoja"]
indx = [1, 4]
از این a میخوایم ایندکس یک یعنی qarpoz و ایندکس چهار یعنی qoja رو حذف کنیم. با روش کاهش ایندکس کد به این شکل میشه:
for i in range(len(indx)):
indx_to_del = indx.pop(0)
del a[indx_to_del]
indx = [n - 1 for n in indx]
در روش بالا ابتدا به تعداد indx یک حلقه ایجاد کردیم تو این کیس بدنه حلقه دوبار اجرا خواهد شد چون indx دوتا عنصر بیشتر نداره ۱ و ۴
بعد اومدیم اولین ایندکس باید دیلیت کنیم رو توسط متد pop انتخاب کردیم اگه نمی دونید پاپ چیکار میکنه سرچ بزنید
بعد توسط دستور del
ایندکسی که پاپ به ما داده رو دیلیت کردیم
نکته اساسی خط بعد هست از اونجایی که یک آیتم از لیست حذف شده الان عنصر ایندکس چهارم به ایندکس ما قبل خودش یعنی ایندکس سوم منتقل شده پس هر ایندکس که در indx هست رو باید یه دونه کاهش بدیم که خط بعدی اون کار به صورت لیست کامپرهشن انجام داده.
این روش کاملا مبتدی وآر و مستعد خطا هست پس بهتره بریم سراغ روش بعدی
روش دوم: پریدن از روی آیتم های که باید حذف بشن
در این روش یک لیست جدیدی میسازیم که شامل همه اعضای لیست هست منتها فاقد عناصری هست که باید حذف بشن.
res = []
for i, elm in enumerate(a):
if i in indx:
continue
else:
res.append(elm)
در این روش ایندکس عناصر a بررسی میشن تا ببینم در لیست indx وجود دارن یا نه. اگر وجود داشته باشن که هیچ کاری نمیکنم یعنی از روی اون عنصر میپریم اگه نه عنصر رو به لیست res اضافه میکنیم. در نهایت لیست res شامل عناصری میشه که ایندکس اونها در indx نیست. نسخه ساده شده کد بالا میتونه به شکل زیر باشه.
res = [elm for i, elm in enumerate(a) if i not in indx]
روش سوم: شروع حذف از بزرگترین ایندکس
در این روش ابتدا ایندکس ها رو از بزرگ و به کوچیک مرتبط میکنیم. در این روش چون ایندکس بزرگتر جلوتر حذف میشه پس ایندکس بعدی کوچکتر هست پس جایگاهش تغییری پیدا نکرده یعنی به جای اینکه از چپ به راست در لیست حرکت کرده و حذف کنیم از راست به چپ حرکت کرده و دیلیت میکنیم:
for i in sorted(indx, reverse=True):
del a[i]
به همین راحتی. ولی با پکیج numpy راحتر هم میشه
روش چهارم استفاده از پکیج numpy
import numpy as np
a = ["moz", "qarpoz", "portakhal", "alma", "qoja"]
a = np.array(a)
indx = [1, 4]
elms = np.delete(a, indx)
همین خط بالایی کافی هست تا چندین عنصر بر اساس ایندکس حذف بشن.