使用 for 循环删除列表中的项目

Posted

技术标签:

【中文标题】使用 for 循环删除列表中的项目【英文标题】:Delete item in a list using a for-loop 【发布时间】:2011-01-04 16:07:25 【问题描述】:

我有一个包含主题的数组,每个主题都有连接时间。我想比较列表中的每个主题。如果有两个相同的主题,我想添加两个主题的时间,还想删除第二个主题信息(主题名称和时间)。

但如果我删除该项目,列表会变短,并且会出现超出范围的错误。我尝试使用 subjectlegth-1 使列表更短,但这也不起作用。

   ...
   subjectlegth = 8
   for x in range(subjectlength):
        for y in range(subjectlength):
            if subject[x] == subject[y]:
                if x != y:
                    #add
                    time[x] = time[x] + time[y]
                    #delete
                    del time[y]
                    del subject[y]
                    subjectlength = subjectlength - 1

【问题讨论】:

看看docs.python.org/tutorial/… 【参考方案1】:

如果可以的话,向后迭代:

for x in range(subjectlength - 1, -1, -1):

y 也是如此。

【讨论】:

虽然这“解决”了您在迭代列表时如何删除列表元素的问题,但更大的问题是您实际上是在迭代列表时修改列表。每当您考虑这样做时,请退后一步,看看您是否可以通过构建具有所需值的新列表来重新解决问题。在这种情况下,您正在收集类似主题的时间值 - 想想“dict”,这是一个更好的结构。如果使用 Python 2.5 或更高版本,请考虑“defaultdict”,它比 dict.get() 更容易使用。 Ignacio Vazquez-Abrams 的答案是正确的。【参考方案2】:

最佳做法是创建一个新的要删除条目列表,并在遍历列表后将其删除:

to_del = []
subjectlength = 8
for x in range(subjectlength):
    for y in range(x):
        if subject[x] == subject[y]:
            #add
            time[x] = time[x] + time[y]
            to_del.append(y)

to_del.reverse()
for d in to_del:
    del subject[d]
    del time[d]

【讨论】:

【参考方案3】:

如果subject 的元素是可散列的:

finalinfo = 

for s, t in zip(subject, time):
  finalinfo[s] = finalinfo.get(s, 0) + t

这将产生一个带有subject: time 键值对的字典。

【讨论】:

【参考方案4】:

另一种方法是重新创建主题和时间列表,使用 dict 来总结重复主题的时间(我假设主题是字符串,即可散列)。

subjects=['math','english','necromancy','philosophy','english','latin','physics','latin']
time=[1,2,3,4,5,6,7,8]
tuples=zip(subjects,time)
my_dict=
for subject,t in tuples:
    try:
        my_dict[subject]+=t
    except KeyError:
        my_dict[subject]=t
subjects,time=my_dict.keys(), my_dict.values()
print subjects,time

【讨论】:

了解 dict.get() 甚至更好的 collections.defaultdict。比 try-except KeyError 干净得多。为什么要打印出keys() 和values()? items() 呢? 我知道 get 和 defaultdict,但不确定 OP 是否如此,所以我坚持采用一种假设知识较少的方法。至于keys() 和values(),OP 想要两个单独的列表,items() 返回一个(key,value) 元组的列表。 @MAK - 很公平,只要您尽可能少地干扰 OP 的原始设计。但是将匹配的数据值保存在单独的列表中的程序真的应该重做以使用字典。如果设计要求添加讲师或房间号怎么办?是否应该通过添加更多对订单敏感的列表来添加这些?通过假设 dict 概念超出了他/她的范围,您对 OP 造成了伤害。 @Paul McGuire:这些是你应该对 OP 说的话,而不是我。我不是假设 dict 概念超出了他的范围,我是在防范他可能对 dicts 还不够熟悉的可能性。【参考方案5】:

虽然while 循环肯定是更好的选择,但如果您坚持使用for 循环,可以将list 要删除的元素替换为None,或任何其他可区分的项目,并在for 循环之后重新定义list。以下代码从整数列表中删除偶数元素:

nums = [1, 1, 5, 2, 10, 4, 4, 9, 3, 9]
for i in range(len(nums)):
  # select the item that satisfies the condition
  if nums[i] % 2 == 0:
    # do_something_with_the(item)
    nums[i] = None  # Not needed anymore, so set it to None
# redefine the list and exclude the None items
nums = [item for item in nums if item is not None]
# num = [1, 1, 5, 9, 3, 9]

就本帖中的问题而言:

...
for i in range(subjectlength - 1):
  for j in range(i+1, subjectlength):
    if subject[i] == subject[j]:
      #add
      time[i] += time[j]
        # set to None instead of delete
        time[j] = None
        subject[j] = None
time = [item for item in time if item is not None]
subject = [item for item in subject if item is not None]

【讨论】:

以上是关于使用 for 循环删除列表中的项目的主要内容,如果未能解决你的问题,请参考以下文章

为啥 for 循环不遍历列表中的每个项目?

如何在不使用 for 循环的情况下将列表中的所有项目与整数进行比较

使用FOR循环来比较列表中的项目和ARRAY中的项目。

在 for 循环期间为列表中的项目分配新值不起作用?

如何使用 for 循环将列表中的子值相互比较?

从嵌套for循环中的指针集中删除项目