2013-11-25 56 views
1

当有多个列表传入函数时,第一个打印系统工作。但是,当传入只有一个列表时,出现错误“AttributeError:'int'object has no attribute'pop'”为什么我的代码不适用于单个列表,但适用于嵌套列表?

此代码尝试从列表中删除一个项目以查看是否仍然弹出该项目存在于剩余的列表中。

def check_row(p): 
    for e in p: 
     while e: 
      x = e.pop() 
      if x in e: 
       return False 
    return True 


print check_row([[8,2,3,4,5], 
       [2,3,1,5,6], 
       [4,0,2,3,1]]) 

print check_row([1,2,3,4,5]) 

非常感谢。

回答

2

您从元素中弹出该项目,而不是外部列表。如果你的元素不是列表,那么不要试图像这样对待它们。

但是,您不能从外部列表中删除项目,同时循环它并期望循环不跳转项目。

如果你想看看发生了项目比列表中的一次,比较列表,而不是set()长度:

def check_row(row): 
    return len(row) == len(set(row)) 

这只适用于可哈希值,嵌套的列表是不,但至少不会像你的代码那样改变列表。

你仍然可以使用列表扫描,但随后至少使用list.index()限制超越当前位置的搜索开始索引:

def check_row(row): 
    for i, elem in enumerate(row): 
     try: 
      row.index(elem, i + 1) 
      return False # dupe found 
     except ValueError: 
      pass # no dupe found 
    return True 

然而,这种假设你想只测试外列表重复。在相同的代码中支持嵌套结构和平面结构,而没有关于每种情况下预期发生的更多细节,则要复杂得多。

+2

我很困惑...您的示例代码将适用于平面列表的情况下,但不是嵌套列表的情况下,因为'列表'不是哈希... – mgilson

+0

@mgilson:darn,那是真的;这将仅适用于列表中的可哈希值。 –

+0

@mgilson:但是,我怀疑OP并不意味着在嵌套列表上使用它,只发现代码不起作用*除非他使用嵌套列表。 –

2

如果是单个(非嵌套)列表,请在元素(e)上调用.pop(),这些元素不是列表,因此可能没有.pop方法。

1

这是因为e是您的列表中的一个元素。在嵌套的一个中,e是一个列表,而在第二个中,e是一个整数。因此,e.pop对于第二个无效。

你必须使其始终嵌套:

>>> print(check_row([[1, 2, 3, 4, 5]])) 
True 

这种方式,传递给check_row值始终是一个嵌套列表,即使它只有一个元素。

但是,至于检查元素是否仍然在其他列表中,我会首先弄平列表,然后检查列表中是否有重复的元素。

import collections 
def flatten(l): 
    for el in l: 
     if isinstance(el, collections.Iterable) and not isinstance(el, str): 
      for sub in flatten(el): 
       yield sub 
     else: 
      yield el 

def check_row(p): 
    flat = list(flatten(p)) 
    return len(flat) == len(set(flat)) 

这样,check_row总是会产生你想要的结果,而忽略它的列表或嵌套列表:)

希望这有助于事实!

0

你在命名时感到困惑。您调用check_row的函数实际上会检查行的列表,尽管该名称存在,所以将其传递给单行失败。你使用毫无意义的单字母名称也无济于事。让我们重写它更清楚:

如果你想要一个检查单排功能,

def check_rows(rows): 
    for row in rows: 
     while row: 
      element = row.pop() 
      if element in row: 
       return False 
    return True 

现在,应该是更清楚失败的原因:你传入一个rowrows,所以for row in rows正在获取元素而不是行,并且从那里开始下坡。


你可能想要的是一个check_row功能在同一行上的作品,然后check_rows即每行调用check_row

def check_row(row): 
    while row: 
     element = row.pop() 
     if element in row: 
      return False 
    return True 

def check_rows(rows): 
    for row in rows: 
     if not check_row(row): 
      return False 
    return True 

不过说真的,我不知道知道你为什么想要这个功能。它破坏性地修改行,删除每个元素直到第一个副本。你为什么要这样?例如,马亭皮特斯的解决方案更简单,更高效,以及作为非破坏性:

def check_row(row): 
    return len(set(row)) == len(row) 

虽然我们在这,让我们使用all功能,而不是外在的循环为check_rows

def check_rows(rows): 
    return all(check_row(row) for row in rows) 
相关问题