从列表中删除相邻的重复元素。

19

谷歌 Python 课程 | 列表练习 -

给定一个数字列表,返回一个新的列表,其中所有相邻的相等元素都被缩减为单个元素。例如[1, 2, 2, 3] 返回 [1, 2, 3]。你可以创建一个新的列表或修改传入的列表。

我的解决方案(使用一个新列表)是 -

def remove_adjacent(nums):
  a = []
  for item in nums:
    if len(a):
      if a[-1] != item:
        a.append(item)
    else: a.append(item)        
  return a
问题甚至提出可以通过修改传入的列表来实现。然而,Python文档警告我们不要在使用for循环迭代列表时修改元素。
我想知道除了遍历列表之外还有什么可以尝试来完成这个任务。我不是在寻找解决方案,但也许有一个提示可以帮助我朝着正确的方向前进。
更新:
- 根据建议改进了上面的代码。
- 使用建议的提示尝试了while循环的以下方法 -
def remove_adjacent(nums):
  i = 1
  while i < len(nums):    
    if nums[i] == nums[i-1]:
      nums.pop(i)
      i -= 1  
    i += 1
  return nums

1
请不要使用<>,正确的表示法是!=。使用if a,而不是if len(a) <> 0 - Katriel
@Aran-Fey 我个人认为,这个问题和重复的目标都应该被关闭,作为删除具有连续重复项的元素的重复。 - Georgy
17个回答

0

看到 Google 写的代码真是让人望尘莫及,哈哈。这是我想出来的:

def remove_adjacent(nums):
   rmvelement = []
   checkedIndex = []
   for num in nums:
      if nums.index(num) not in checkedIndex:
         index = nums.index(num)
         checkedIndex.append(index)
         skip = False
      else:
         skip = True

   if skip == False:
      for x in nums[index+1:]:
         if x == num:
            rmvelement.append(x)
         else:
            break

   [nums.remove(_) for _ in rmvelement]
   return nums

0

@katrielalex的解决方案更符合Python语言风格,但如果你需要在不复制列表的情况下就地修改它,可以使用while循环,并在捕获IndexError时中断。 例如:

nums = [1,1,1,2,2,3,3,3,5,5,1,1,1]
def remove_adjacent(nums):
    """Removes adjacent items by modifying "nums" in-place. Returns None!"""
    i = 0
    while True:
        try:
            if nums[i] == nums[i+1]:
                # Letting you figure this part out, 
                # as it's a homework question
        except IndexError:
            break
print nums
remove_adjacent(nums)
print nums

编辑:这里有一种方法的 pastebin 链接,如果您卡住了并想知道如何处理..


我尝试了一下提示,并更新了我的尝试。 - Vaibhav Bajpai

0

如果您明确使用索引,可以修改正在迭代的列表:

def remove_adjacent(l):
  if len(l)<2:
    return l
  prev,i = l[0],1
  while i < len(l):
    if l[i] == prev:
      del l[i]
    else:
      prev = l[i]
      i += 1

它不能与迭代器一起使用,因为迭代器不知道如何在删除任意元素时修改索引,所以禁止这样做更容易。一些语言具有带有删除“当前项目”的函数的迭代器。


(1) 不要使用 "l" 作为变量名称;在某些字体中,它看起来太接近 "1" (2) 如果列表长度小于 2,则您的函数返回原始列表,否则返回 None ... 有点不一致。 - John Machin
l是一个非常好的变量名。如果你的代码字体不能区分l、I、1、0、O,那么你需要一个更好的字体。 - tc.

0
def removeDupAdj2(a):
    b=[]
    for i in reversed(range(1,len(a))):
        if(a[i-1] == a[i]):
            del(a[i])
            #print(a)
    return a

a = [int(i) for i in '1 2 3 3 4 4 3 5 4 4 6 6 6 7 8 8 8 9 1 1 0 0'.split(' ')]
a

res = removeDupAdj2(a)
res

0

def remove_adjacent(nums):

newList=[]

for num in nums:

    if num not in newList:

        newList.append(num)

newList.sort()

return  newList

这并没有回答问题。 - AndJM

0

这应该适用于一个透明(虽然迂回)的解决方案:

def remove_adjacent(nums):

    numstail = [i for i in range(0,len(nums))] 
    nums = nums + numstail

    for i in nums:
        if nums[i] == nums[i-1]:
            del nums[i]

    return nums[:-len(numstail)]

逻辑如下:

  • 创建一个尾部列表,其长度等于原始数字列表的长度,并将其附加到原始列表的末尾。
  • 运行一个“for循环”,检查nums的给定元素是否与前一个元素相同。如果是,则删除它。
  • 返回新的nums列表,其中包含必要的删除操作,直到从列表末尾算起的len(numtails)索引位置。

(为避免任何长度的列表超出范围,定义了numstail


-3

既然你正在学习Python课程,我猜想你可能是这门语言的新手。因此,为了帮助你和其他初学者,我编写了一个简单版本的代码,以帮助大家理解逻辑。

original= [1, 2, 2, 3]
newlist=[]

for item in original:
    if item in newlist:
        print "You don't need to add "+str(item)+" again."
    else:
        newlist.append(item)
        print "Added "+str(item)

print newlist

1
但它只要求删除相邻的项,上面的代码将不考虑它们的位置而不让任何重复项存在,因此本质上[1,2,3,2]将产生[1,2,3],而应该产生[1,2,3,2]。 - Vaibhav Bajpai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接