【问题标题】:modify lists removing elements without making a mess修改列表删除元素而不造成混乱
【发布时间】:2016-10-18 09:29:44
【问题描述】:

我现在正在尝试解决一个听起来像这样的任务:

''编写一个函数 modi(la, lb),它接受输入 2 列表 la 和 lb,其中包含相同数量的元素。该函数应该修改列出两个列表中具有相同索引的 la 和 lb 露营元素,并删除一个更大的元素,如果元素相等,则删除它们。 ''

例如:

  • la = ['熊', '老虎', '狼', '鲸', '大象']
  • lb = ['swan', 'cat', 'dog', 'duck', 'rabbit']

所以函数应该返回: ['熊','大象'] ['猫','狗','鸭子']

我已经编写了下一个代码,但它不会修改列表而是创建新列表并添加元素。一些想法我该怎么做?

def confront(s1, s2):   

    if s1 < s2:   # condition that tells which element to choose later
        return 0
    elif s2 < s1:
        return 1
    else:
        return 2


def modi(la,lb):

    latemp = []

    lbtemp = []

    i = 0

    while i < len(la):


        q = confront(la[i], lb[i])
        if q == 0:
            latemp.append(la[i])

        elif q == 1:
            lbtemp.append(lb[i])


        i +=1  
    la = latemp
    lb = lbtemp
    return la, lb

我尝试过 remove(),但它造成了很大的混乱

【问题讨论】:

  • 不应该是[]['cat','dog','duck','rabbit']吗?

标签: python list python-3.x


【解决方案1】:

通常,当您在迭代列表时对其进行变异时。最好是迭代副本。下面是一个示例,说明您将如何改变一个列表。

list = []
list_copy = list[:]
for i in list_copy:
    list.remove(i)
return list

这允许您在每次迭代时维护正确的索引。

以下是我试图解释我的意思并使用 for 循环来获得预期结果的尝试。希望对您有所帮助。

def confront(s1, s2):

if s1 < s2:   # condition that tells which element to choose later
    return 0
elif s2 < s1:
    return 1
else:
    return 2


def modi(la,lb):
    la_copy = la[:]
    lb_copy = lb[:]

    for i in range(len(la_copy)):
        q = confront(la_copy[i], lb_copy[i])
        if q == 0:
            lb.remove(lb_copy[i])
        elif q == 1:
            la.remove(la_copy[i])

    return la, lb


la = ['bear', 'tiger', 'wolf', 'whale', 'elephant']
lb = ['swan', 'cat', 'dog', 'duck', 'rabbit']

通过 print() 调用它会得到返回的两个列表。

注意:这会返回一个元组。如果您想要单独的列表,请通过以下方式调用它。

list1, list2 = modi(la,lb)
print(list1)
print(list2)
['bear', 'elephant']
['cat', 'dog', 'duck']

【讨论】:

    【解决方案2】:

    在您自己的代码la = latemplb = lbtemp 中为函数本地的两个新列表创建引用,它们与您传递给函数的列表无关。根据您的规范,您应该改变传入的列表,而不是重新分配或创建新列表。

    由于您正在进行元素比较,您可以使用 zip 并根据您的规格从每个列表中删除:

    def modi(la, lb):
        for i, j in zip(la, lb):
            # both the same
            if i == j:
                la.remove(i) 
                lb.remove(i)
            # element from la is bigger
            elif i > j:
                la.remove(i)
            # else element from lb must be bigger
            else:
                lb.remove(j)
    
    
    la = ['bear', 'tiger', 'wolf', 'whale', 'elephant']
    lb = ['swan', 'cat', 'dog', 'duck', 'rabbit']
    
    modi(la, lb) # will modify the lists passed in.
    
    print(la, lb) 
    

    【讨论】:

      【解决方案3】:

      您应该使用del 删除列表项。此外,您应该从头到尾迭代,因为如果您要从头开始并删除 1st 元素,则位于 3rd 位置的元素现在将位于 2nd

      应该是这样的

      #you need to handle what if len of lists is 0, if lens are not the same and so on...
      def compare_and_delete(list1, list2):
          i = len(list1) -1
          while i >= 0:
              if list1[i] > list2[i]:
                  del list1[i]
              elif list2[i] > list1[i]:
                  del list2[i]
              else:
                  del list1[i]
                  del list2[i]
      
              i-=1
      
              return list1, list2
      
      l1, l2 = compare_and_delete(['bear', 'tiger', 'wolf', 'whale', 'elephant'], ['swan', 'cat', 'dog', 'duck', 'rabbit'])
      

      【讨论】:

      • 谢谢!我有一个学习编程仅 3 周的无知者的问题:返回这个函数是什么?因为当我运行它时它什么也不返回.....
      • 是的 - 你需要添加 return 语句查看我的编辑
      【解决方案4】:

      基本上,您需要跟踪从每个列表中删除了多少次,并按该数量抵消您的索引。这是一个基本的方法:

      >>> a
      ['bear', 'tiger', 'wolf', 'whale', 'elephant']
      >>> b
      ['swan', 'cat', 'dog', 'duck', 'rabbit']
      >>> i = j = 0
      >>> for k, (str1,str2) in enumerate(zip(a,b)):
      ...     if len(str1) == len(str2):
      ...         del a[k-i], b[k-j]
      ...         i += 1
      ...         j += 1
      ...     elif len(str1) > len(str2):
      ...         del a[k-i]
      ...         i += 1
      ...     else:
      ...         del b[k-j]
      ...         j += 1
      ... 
      >>> a
      []
      >>> b
      ['cat', 'dog', 'duck', 'rabbit']
      >>> 
      

      【讨论】:

        【解决方案5】:

        这将解决您的问题。我认为它比所有其他解决方案都容易。

        def modi(la, lb):
            new_la = []
            new_lb = []
            for a, b in zip(la, lb):
                if a == b:
                    continue
                if a > b:
                    new_lb.append(b)
                if a < b:
                    new_la.append(a)
            return new_la, new_lb
        

        但是,如果您想更改现有列表,您可以这样做:

        def modi(la, lb):
            del_la = []
            del_lb = []
            for i, (a, b) in enumerate(zip(la, lb)):
                if a == b:
                    del_la.append(i)
                    del_lb.append(i)
                if a > b:
                    del_la.append(i)
                if a < b:
                    del_lb.append(i)
            for x in del_la[-1::-1]:
                del la[x]
            for x in del_lb[-1::-1]:
                del lb[x]
            return la, lb
        

        【讨论】:

        • modi(la,lb) 函数应该修改列出lalb,但您的解决方案没有。
        • 这就是问题所在。我以同样的方式在开头创建空列表并在其中添加元素,所以最后我返回新列表。
        • 我添加了另一个解决方案(基于第一个)来更改现有列表。
        • 对不起,我还没有看到你的第二个代码!现在我明白了,我想问一下 'enumerate(zip(la, lb))' 是什么意思
        • zip 用于同时遍历两个列表,直到到达较短列表的末尾。 enumerate 只是枚举for 循环中的传递(这很适合以后用作索引)。如果你喜欢这个答案,请采纳。
        【解决方案6】:

        您可以利用分配给切片会修改列表的事实:

        la[:] = latemp
        lb[:] = lbtemp
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-12-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多