Переместить нули в конец списка, оставив False в покое - PullRequest
0 голосов
/ 22 декабря 2018

У меня есть некоторый код, который должен найти положение любых элементов 0 в списке и переместить его назад, сохраняя при этом порядок других элементов.

def test2(array):
    try:
        for n in range(len(array)):
            array.append(array.pop(array.index(0)))
        return array
    except ValueError:
        return array

Этот код отлично работает длялюбой список кроме одного с False в. Я думаю, это потому, что .index(0): также вернет позицию любого False в списке.Любой способ обойти это?

Например, если array = [0,1,None,2,False,1,0], то результат должен быть [1,None,2,False,1,0,0]

С тем же входным сигналом мой код выдает: [1, None, 2, 1, False, 0, 0]

Ответы [ 6 ]

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

Python гарантирует True и False - единственные экземпляры bool, поэтому вы можете использовать is, чтобы отличить False от 0.

z = []
return [e for e in array if e is False or e != 0 or z.append(e)] + z

Это сохранит порядок различных не False нулей (0, 0.0, 0j, Decimal(0), Fraction(0, 1)), которые могут быть в списке.

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

Я думаю, что это так кратко, как это может быть.Спасибо всем за помощь

l = [i for i in array if isinstance(i, bool) or i!=0]
return l+[0]*(len(array)-len(l))
0 голосов
/ 22 декабря 2018

Вы можете использовать оболочку с пользовательским __eq__:

class Typed:
    def __init__(self, val):
        self.val = val
    def __hash__(self):
        return hash(self.val)
    def __eq__(self, other):
        if isinstance(other, Typed):
            other = other.val
        return type(self.val) is type(other) and self.val == other

Затем замените array.index(0) на array.index(Typed(0)) - вам не нужно использовать это в самом массиве.

Расширение этого на контейнеры (так что (0, 1) и (False, True) не будут равны) оставлено в качестве упражнения для читателя.

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

Вариант решения @ coldspeed:

array = [0, 1, None, 2, False, 1, 0]
nonzero = [x for x in array if x or x is None or isinstance(x,bool)]
nonzero + [0] * (len(array) - len(nonzero))
# [1, None, 2, False, 1, 0, 0]
0 голосов
/ 22 декабря 2018

Если создание другого списка не представляет интереса, вы можете использовать списочные выражения:

def test2(array):
    la = len(array)
    return ([x for x in array if not isinstance(x,int) or x]+[0]*la)[:la]

Первая часть отфильтровывает любое целое число 0, но пропускает любой не-int.Вторая часть добавляет (слишком много) нулей и обрезает результат до первоначальной длины.

Предостережение: Это приведет к удвоению исходной длины списка в данных - поэтому неподходит для "больших" списков или списков с несколькими 0.

Использование:

k = [1,2,3,0,4,5,False,92,-3,0,1,0,0,True,[],None,True]
print(k)
print(test2(k))

Вывод:

[1, 2, 3, 0, 4, 5, False, 92, -3, 0, 1, 0, 0, True, [], None, True]
[1, 2, 3, 4, 5, 92, -3, 1, True, True, 0, 0, 0, 0, 0, 0, 0]

Доку:

  • (связанный) Проверка правды - есть и другие значения, которые также являются "Ложными".
0 голосов
/ 22 декабря 2018

Это является следствием того факта, что bool является подклассом int в python, поэтому поиск первого индекса 0 вернет индекс False, если он находится в списке ранее.a 0 потому что False == 0.

Что вы можете сделать, это проверить, является ли элемент списка экземпляром int, и в то же время не экземпляром bool.Таким образом, вы избегаете сопоставления других ложных значений (например, пустых контейнеров и None).

def is_zero(v):
    # return is instance(v, int) and v is not False and not v
    # return isinstance(v, int) and not isinstance(v, bool) and not v
    return type(v) in (int, float) and not v

Затем вы можете перебирать lst в обратном порядке и обновлять на месте.

lst = [1, 0, None, False, 0, 3, True] # For example.

for i in reversed(range(len(lst))):
    if is_zero(lst[i]):
        lst.append(lst.pop(i))

print(lst)
# [1, None, False, 3, True, 0, 0]

Это амортизированная линейная сложность по времени, если я не ошибаюсь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...