2件Python代码之间的区别

时间:2010-12-22 11:00:15

标签: python list

我正在做一个练习如下:

# B. front_x
# Given a list of strings, return a list with the strings
# in sorted order, except group all the strings that begin with 'x' first.
# e.g. ['mix', 'xyz', 'apple', 'xanadu', 'aardvark'] yields
# ['xanadu', 'xyz', 'aardvark', 'apple', 'mix']
# Hint: this can be done by making 2 lists and sorting each of them
# before combining them.

样本解决方案:

def front_x(words):
  listX = []
  listO = []

  for w in words:
    if w.startswith('x'):
      listX.append(w)
    else:
      listO.append(w)

  listX.sort()
  listO.sort()

  return listX + listO

我的解决方案:

def front_x(words):
  listX = []

  for w in words:
    if w.startswith('x'):
      listX.append(w)
      words.remove(w)

  listX.sort()
  words.sort()

  return listX + words  

当我测试我的解决方案时,结果有点奇怪。以下是我的解决方案的源代码:http://dl.dropbox.com/u/559353/list1.py。你可能想尝试一下。

4 个答案:

答案 0 :(得分:3)

问题是你循环遍历列表并从中删除元素(修改它):

for w in words:
    if w.startswith('x'):
      listX.append(w)
      words.remove(w)

示例:

>>> a = range(5)
>>> for i in a:
...  a.remove(i)
... 
>>> a
[1, 3]

此代码的工作原理如下:

  • 获取第一个元素,将其删除。
  • 移至下一个元素。但它不再是1因为我们之前删除了0,因此1成为新的第一个元素。因此,下一个元素为2,并且会跳过1
  • 34相同。

答案 1 :(得分:1)

两个主要区别:

  1. 从迭代列表循环中的列表中删除元素在Python中不起作用。如果您使用的是Java,那么您将获得一个异常,即您正在修改正在迭代的集合。 Python并没有明显地喊出这个错误。 @Felix_Kling在他的回答中解释得非常好。
  2. 您还要修改输入参数words。因此,函数front_x的调用者将在执行函数后看到words被修改。除非明确预期,否则此行为最好避免。想象一下,您的程序正在使用words执行其他操作。保留sample solution中的两个列表是一种更好的方法。

答案 2 :(得分:0)

更改您正在迭代的列表会导致未定义的行为。这就是示例解决方案创建两个新列表而不是从源列表中删除的原因。

for w in words:
  if w.startswith('x'):
    listX.append(w)
    words.remove(w) # Problem here!

有关此问题的讨论,请参阅this question。它基本上归结为列出遍历列表索引的迭代器,而不返回并检查修改(这将是昂贵的!)。

如果要避免创建第二个列表,则必须执行两次迭代。一个用于迭代words以创建listX而另一个用于迭代listXwords删除。

答案 3 :(得分:0)

该提示具有误导性和不必要性,您无需单独排序和组合两个列表即可完成此操作:

>>> items = ['mix', 'xyz', 'apple', 'xanadu', 'aardvark']
>>> sorted(items, key=lambda item: (item[0]!='x', item))
['xanadu', 'xyz', 'aardvark', 'apple', 'mix']

内置的sorted()函数接受一个选项键参数,告诉它要排序的内容。在这种情况下,您希望为原始列表的每个元素创建一个类似(False,'xanadu')或(True,'apple')的元组,您可以使用lambda。