Я пишу функцию для перемещения 0 в конец списка, но когда значение False находится в списке, оно преобразует его в 0 и также перемещает в конец.
Я пробовал много вариантов операторов if, включая:
если я == 0
если type(i) != bool и i == 0
если ул(я) == '0'
def move_zeros(array):
for i in array:
if str(i) == '0' and str(i) != 'False':
array.remove(i)
array.append(0)
return array
В случае [0,1,None,2,False,1,0]
я ожидал, что функция вернет [1,None,2,False,1,0,0]
, но вместо этого она вернула [1,None,2,1,0,0,0]
.
У вас есть две проблемы здесь. Во-первых, в Python bool
является подклассом int
и False == 0
, поэтому, чтобы отличить 0
от False
, вам нужно проверить тип вашего объекта. Кроме того, изменение списка на месте во время его повторения является верным рецептом для ошибок «выключения».
Вот простая глупая простая реализация, которая работает:
def move_zeros(seq):
head, tail = [], []
for v in seq:
if isinstance(v, int) and not isinstance(v, bool) and v == 0:
tail.append(v)
else:
head.append(v)
return head + tail
рад, что смог помочь - и тогда не стесняйтесь голосовать за мой ответ. Вы также можете проголосовать и принять ответ Лепорелло, который точнее моего.
Я новичок в стеке, буквально зарегистрировался час назад, поэтому я проголосовал за ваш ответ и за ответ Лепорелло, но я думаю, что он не будет отображаться, когда у меня меньше 15 репутации.
@hubvoy спасибо за нас обоих 8-) - и, пожалуйста, не забудьте ответ принимать leporello, который заслуживает того, чтобы быть отмеченным здесь как единственный правильный ответ (помните, что SO предназначен для создания базы технических знаний, поэтому принятие лучшего решения важно для будущие читатели).
хорошо, принять ответ - это просто поставить галочку под счетчиком голосов, верно?
Здесь есть пара подводных камней. Один из них, который вы уже поняли, заключается в том, что не существует тривиального способа различать 0
и False
. Однако есть еще два момента:
array.remove()
делает не то, что вы думаете. Это удаляет из array
первый элемент, который является ==
своим аргументом, который может быть или не быть в той же позиции, что и элемент в итерационном цикле. Это отвечает за превращение вашего False
в 0
.Имея это в виду, вот рабочая версия:
def is_integer_zero(x):
# The cleanest way I found, but you could argue for other options
return x == 0 and not isinstance(x, bool)
def move_zeros(array):
left_part = []
right_part = []
for i in array:
if is_integer_zero(i):
right_part.append(i)
else:
left_part.append(i)
return left_part + right_part
l = [0, 1, None, 2, False, 1, 0]
print(move_zeros(l)) # [1, None, 2, False, 1, 0, 0]
right_part
полностью состоит из нулей, так что вы могли бы немного упростить код/улучшить производительность, но у этой версии есть то преимущество, что вы можете использовать другие условия, чтобы выбрать, что сдвигать вправо.
если вы хотите сделать его более общим, рассмотрите возможность передачи функции предиката (здесь is_integer_zero
) в качестве обратного вызова. Совершенно очевидно, что для проблемы ОП, но поскольку вы упомянули «использование других условий»... ;-)
Спасибо, я также добавил или isinstance(v,float) для возможных значений 0.0