2013-10-21 61 views
0

我被困在做一个循环,将消除低于平均值的值(来自alist)。 感谢您的帮助。循环列表(Python v3)初学者

a=input("Enter a list of values separated by a coma : ") 
alist=eval(a) 
print("the list is : ",alist) 

average = sum(alist)/len(alist) 
print("the average is : ",average) 

for i in alist: 
    if alist[i]<average: 
     alist.remove[i] 
+0

应避免使用'eval'。请参阅http://stackoverflow.com/questions/1832940/is-using-eval-in-python-a-bad-practice。 – jpmc26

回答

4

你快到了。而不是删除元素,你要选择的元素,而不是保留:

alist = [a for a in alist if a>=average] 

你这里的错误是for i in alist:是在列表中的元素进行迭代自己,没有指标,所以alist[i]抛出一个错误(或返回废话)。

3

对于“循环”您可以使用filterlambda功能。

above_average = list(filter(lambda x: x >= average, alist)) 

为了您的代码的其余部分,我建议你清理的东西是安全的(使用eval是非常糟糕)

import ast 
user_string = raw_input('input a list of numbers separated by a commas: ') 
alist = list(ast.literal_eval(user_string))) 

所以,在所有的,我会写下你的代码,如下所示:

import ast 
user_string = raw_input('input a list of numbers separated by a commas: ') 
numbers = list(ast.literal_eval(user_string))) 
average = sum(numbers)/len(numbers) 
print('The numbers: {}'.format(numbers)) 
print('The average: {}'.format(average)) 
above_average = list(filter(lambda x: x >= average, numbers)) 
# now do what you want with the above_average numbers. 
+1

['literal_eval'](http://docs.python.org/2/library/ast.html#ast.literal_eval)不是那么邪恶,在这种情况下可能和'eval'一样好用,会避免'split'和'map'到'int'。 – jpmc26

+1

'literal_eval'将''1,2,3,4''这样的字符串转换为整数列表的唯一方法就是通过魔术。你需要让字符串看起来像'“[1,2,3,4]”,这意味着在字符串的开始和结尾附加和预先加上一个方括号。看起来像这样:'alist = ast.literal_eval('[{}]'。format(user_string))'分割和映射有什么问题? –

+0

刚刚在Python 2.7中测试过。 '“1,2,3,4”'变成'元组'。由于'tuple's是可迭代的,这不应该成为一个问题。我假设这个语法也延伸到Python 3.x中。 – jpmc26

2

您正在混合迭代列表的两种方式:按索引和按元素。在你的循环中,i不是索引,但列表本身的元素,因此alist[i]将不起作用。

如果使用for x in somelist循环,那么x是元素本身,而不是元素的索引。要遍历索引,可以使用for i in range(len(somelist)),或者可以使用for i, x in enumerate(somelist)来遍历索引和元素的元组。

还要注意,从列表或其他类型的集合移除元素,而你一般循环他们是一个坏主意。更好地创建列表的副本。

for x in list(alist):  # creates a copy of alist 
    if x < average:  # remember: x is the element itselt 
     alist.remove(x) # remove element x from list 

但你这样做(用逗号分隔的数字串的eval)的方式,alist是一个元组,列表,因此没有remove方法可言。因此,您必须先将其转换为列表(alist = list(eval(a))),或者使用其他答案中给出的方法之一,使用列表理解或筛选并保留“好”元素创建新列表。

2

其他答案告诉你该怎么办呢,我会告诉你为什么它不工作:

您遍历列表,并在同一时间,修改

这导致迭代过程中被错过的项目。为什么?

在内部,迭代通过列表的索引工作。所以它和做一样

idx = 0 
while True: 
    try: 
     i = alist[idx] 
    except IndexError: 
     break 
    idx += 1 
    if alist[i] < average: 
     alist.remove(i) 

如果你在元素#3,去下一个,然后删除#3,会发生什么?没错,其余的指标下移,你指的是以前是#5的指标。在这个测试中,旧的#4被跳过。

(顺便说一句,我不知道你注意到没有,我曾与()取代你[]背后.remove

1

作为一般原则,要求StackOverflow的类似这样的问题,您应该包括例如输入和输出 - 展示会发生什么,以及你期望发生的事情。

在这种情况下,我相信有三个问题与您的代码:

编辑:三,但也可能是最重要的,看glglgl's answer。如果你实现了下面描述的两个修复程序,那么你仍然会遇到一个问题:你的代码不一定会删除你想删除的所有项目,因为它会跳过一些项目。

首先,你说alist[i],其中抓起alist元素的索引i。但是说for i in alist已使得i成为列表中的连续元素。例如:

mylist = [1, 2, 4] 
for i in mylist: 
    print(i) 

会给你的输出:

1 
2 
4 

如果你不是说,这(就像你写的)

mylist = [1, 2, 4] 
for i in mylist: 
    print(mylist[i]) 

它不会因为你的工作”因为你会得到索引1处的元素,索引2处的元素,然后尝试获取索引4处的元素,但这不会存在。你会得到这样的事情:

2 
4 
IndexError: list index out of range 

其次,你的语法移除元素是错误的。您应该使用alist.remove(i)而不是alist.remove[i]。你想调用一个函数,所以你使用括号。方括号用于索引和切片。

+0

感谢您的解释,它是完全有道理的。 –