При переборе списка внутри функции, почему 0 не 0.0? - PullRequest
0 голосов
/ 17 декабря 2018

Я пытаюсь решить проблему, в которой я должен удалить нули (как 0, так и 0.0) из списка и добавить их в конец списка (добавляемый ноль может быть 0, не обязательно должно быть 0.0).Но подвох в том, что я не должен удалять False.Я подумал, что наконец-то понял свою проблему, используя is вместо ==, но по какой-то причине это не работает:

arr = [9,0.0,0,9,1,2,0,1,0,1,0.0,3,0,1,9,0,0,0,0,9]
def move_zeros(array):
    temp = array.copy()
    j = 0
    for p, i in enumerate(array):
        if i is 0 or i is 0.0:
            del temp[p - j]
            j += 1
            temp.append(0)
    return temp

print(move_zeros(arr))

Я попытался поместить скобки в оператор if, но результатта же.Он удаляет все 0, но по какой-то причине не удаляет 0.0.Результат:

[9, 0.0, 9, 1, 2, 1, 1, 0.0, 3, 1, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0]

Я переписал функцию, но вне функции, и по какой-то причине она работает:

array = [1, 0, 2, False, 0.0, 4]
for p, i in enumerate(array):
    if i is 0 or i is 0.0:
        del temp[p - j]
        j += 1
        temp.append(0)

И вот результат, как я и ожидал:

[1, 2, False, 4, 0, 0]

Почему ноль с плавающей точкой удаляется при выполнении вне функции, но когда вызывается функция move_zeros, плавающие точки не распознаются в операторе if?

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Вы обрабатываете только floats и ints - так что вы можете создать новый список из вашего ввода, если значение не равно 0:

arr = [9,0.0,0,9,1,2,0,1,0,1,0.0,3,0,1,9,0,0,0,0,9]

def move_zeros(array):
    len_arr = len(array)
    return ([ x for x in array if x != 0.0]+[0]*len_arr)[:len_arr]

# equivalent non-listcomprehension but simple for loop
def m_z(arr):
    k = []
    tmp = []
    for e in arr:
        if e/1.0 != 0.0:
            k.append(e)
        else:
            tmp.append(0)
    return k+tmp

    print(move_zeros(arr))

Вывод:

[9, 9, 1, 2, 1, 1, 3, 1, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Если x является только целым числом 0 и -0 может привести к 0.0 - если x является числом с плавающей запятой, только 0.0 и -0.0 могут привести к 0.0 - просто не помещайте их ввыход..copy() не нужен, потому что понимание списка уже копируется для вас.

Проверка для интергеров и is работает, потому что python кэширует целые числа от -5 до 256 или около того - все они получают одинаковые id()и, следовательно, is «кажется» работает.

Используйте is только для None чеков или, если вы знаете, что делаете, никогда не для чисел.

Если вы хотите оставить не (ìnt,float) нетронутыми, вы можете проверить дляэто тоже:

arr = [9,0.0,0,False,9,1,2,0,1,0,1,0.0,3,0,1,9,0,0,0,0,9]

def move_zeros(array):
    len_arr = len(array)
    return ([ x for x in array if type(x) not in {int,float} or 
             x != 0.0]+[0]*len_arr)[:len_arr]

# [9, False, 9, 1, 2, 1, 1, 3, 1, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Подробнее:


Небольшая проверка работоспособности:

k = 365
i = 365 // 5 * 5  # if you do i = 365 only, they are ==/is True, this way: they are not

for elem in [0,False,k]:
    for olem in [0,False,i]:     
        print(f"{str(elem):>8} is {str(olem):<10}:   {str(elem is olem):<10} ")
        print(f"{str(elem):>8} == {str(olem):<10}:   {str(elem == olem):<10} ")

Выход:

       0 is 0         :   True       
       0 == 0         :   True       
       0 is False     :   False      
       0 == False     :   True       
       0 is 365       :   False      
       0 == 365       :   False      
   False is 0         :   False      
   False == 0         :   True       
   False is False     :   True       
   False == False     :   True       
   False is 365       :   False      
   False == 365       :   False      
     365 is 0         :   False      
     365 == 0         :   False      
     365 is False     :   False      
     365 == False     :   False      
     365 is 365       :   False      # k is i
     365 == 365       :   True       # k == i
0 голосов
/ 17 декабря 2018

используйте ==, а не is.is - для сравнения идентичности (две «вещи», занимающие, по сути, одно и то же пространство в памяти), == - для равенства (две вещи имеют одинаковые определяющие свойства).Кроме того, для поплавков часто бывает полезно проверить, достаточно ли близки вещи, например, is_equal = a-b < 0.00001

...