我正在尝试为数组创建一个函数。数组将进入,如果值为0,它将被放入列表的后面。我的函数大部分时间都在工作,但唯一的问题是布尔值False一直被解释为0.我创建了一个AND语句来区分0和False,但它不起作用,我无法弄清楚为什么。你能不能在列表理解中使用AND语句吗?
def move_zeros(array):
[array.insert(len(array), array.pop(array.index(x))) for x in array if x == 0 and x is not False]
return array
我添加了两个例子。一个有效。另一个不是我想要完成的事情。
输入:[1,“a”,2,0,3,“b”]输出:[1,“a”,2,3,“b”,0]这是有效的
输入:[1,False,2,0,3,“b”]输出:[1,2,3,“b”,False,0]这不起作用,因为False正被移动到当我想要传递它时,列表的末尾。
答案 0 :(得分:1)
替代列表理解的循环。它仍然会修改列表。正如其他人所指出的那样x is 0
简化了0
和False
之间的区别:
In [106]: al=[0, 1, 2, False, True, 3,0,10]
In [107]: for i,x in enumerate(al):
...: if x is 0:
...: value = al.pop(i)
...: al.append(value)
...:
In [108]: al
Out[108]: [1, 2, False, True, 3, 10, 0, 0]
有了这样的副作用,循环比理解更好。理解应该用在:
return [.... for x in al if ...]
感。你也可以在理解中使用枚举:
return [fun(x, i) for i, x in enumerate(al) if x...]
在清晰的列表理解中,列表只出现一次;测试和返回值仅取决于迭代变量,而不取决于原始列表。
===================
请注意0
和False
通常被视为相同。例如,期望数字将False
视为0
,True
视为1的操作。期望布尔值的函数会将0
视为False
。
In [117]: [x+1 for x in al]
Out[117]: [1, 2, 3, 1, 2, 4, 1, 11]
In [118]: al=[0, 1, 2, False, True, 3,0,10]
In [119]: sum(al)
Out[119]: 17
=================
列表推导中and
的示例:
In [137]: [x for x in al if x==0]
Out[137]: [0, False, 0]
In [138]: [x for x in al if x==0 and x is not False]
Out[138]: [0, 0]
In [140]: [x for x in al if not (x==0 and x is not False)]
Out[140]: [1, 2, False, True, 3, 10]
============
另一种可能的测试 - str表示:
In [143]: [x for x in al if str(x)!='0']
Out[143]: [1, 2, False, True, 3, 10]
=====
您的问题不在于测试,而在于al.index(x)
;它匹配0
和False
,并删除第一个,无论哪个x
正在通过您的测试。
带有al.index(x)
的版本:
In [396]: al=[1,False,2, 0,3,"b"]
In [397]: for x in al:
...: if x ==0 and x is not False:
...: al.append(al.pop(al.index(x)))
...:
In [398]: al
Out[398]: [1, 2, 0, 3, 'b', False]
枚举i
In [399]: al=[1,False,2, 0,3,"b"]
In [400]: for i,x in enumerate(al):
...: if x ==0 and x is not False:
...: al.append(al.pop(i))
...:
In [401]: al
Out[401]: [1, False, 2, 3, 'b', 0]
或者在你的功能中:
def move_zeros(array):
[array.insert(len(array), array.pop(i)) for i,x in enumerate(array) if (x == 0 and x is not False)]
return array
In [403]: al=[1,False,2, 0,3,"b"]
In [404]: move_zeros(al)
Out[404]: [1, False, 2, 3, 'b', 0]
单独测试index
:
In [405]: al=[1,False,2, 0,3,"b"]
In [406]: al.index(0)
Out[406]: 1
In [407]: al.index(False)
Out[407]: 1
答案 1 :(得分:0)
在过滤列表时尝试在False
和is
之间进行语义区分可能是一个坏主意,但是如果你有充分的理由这样做有几种方法可以可能适合你的情况。
在CPython中使用的有点hackish方法是使用==
而不是def move_zeros(array):
zeros = 0
new_array = []
for x in array:
if not x is 0:
new_array.append(x)
else:
zeros += 1
return new_array + [0]*zeros
:
isinstance()
正如@chepner所指出的,这是依赖于实现的。在Python 3中使用的更强大的方法是使用def move_zeros(array):
zeros = 0
new_array = []
for x in array:
if x != 0 or isinstance(x,bool):
new_array.append(x)
else:
zeros += 1
return new_array + [0]*zeros
:
>>> move_zeros([1, False, 2, 0, 3, "b"])
[1, False, 2, 3, 'b', 0]
使用任一定义:
#include <stdio.h>
#include <stdlib.h>
// TODO: you should use bool instead
int is_all_space(const char *s)
{
char *tmp;
tmp = (char *) s;
// you might check for '\n' instead in your case
// or even '\r'
while (*tmp != '\0') {
// TODO: this check will fail if the input has zero length
if (*tmp != ' ') {
return 0;
}
tmp++;
}
return 1;
}
// don't forget to put the argument in quotes if it contains spaces
int main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "Usage: %s somestring\n", argv[0]);
exit(EXIT_FAILURE);
}
if (is_all_space(argv[1])) {
puts("Input is all-space and nothing else");
} else {
puts("Input it not all-space");
}
exit(EXIT_SUCCESS);
}