Есть ли способ "разветкить" список по два на основе условия
Я видел образец, повторяемый пару раз в моем командном коде, он выглядит так
numbers = [1, 2, 3, 4]
even_numbers = [n for n in numbers if n % 2 == 0]
odd_numbers = [n for n in numbers if n % 2 != 0]
Мне было интересно, есть ли какая-нибудь функция где-нибудь (я огляделся, но не смог ее найти), что бы сделать что-то вроде этого
numbers = [1, 2, 3, 4]
even_numbers, odd_numbers = fork(numbers, lambda x: x % 2 == 0)
Итак, эта функция, которую я ищу, получит итерабельность и функцию, и вернет два списка, будут значения, которые соответствуют предоставленному условию, а другие - те, которые этого не сделали.
Есть ли что-то вокруг стандартной библиотеки python, которая достигает этого?
Ответы
Ответ 1
Обычно я называю это sift
, но partition
тоже прекрасен.
Другая, безрезультатная реализация может быть
def sift(iterable, predicate):
t = []
f = []
for value in iterable:
(t if predicate(value) else f).append(value)
return (t, f)
even, odd = sift([1, 2, 3, 4, 5], lambda x: x % 2 == 0)
EDIT: для немного более сложной реализации, которая примерно на 30% быстрее (на моей установке Python в любом случае):
def sift2(iterable, predicate):
t = []
f = []
ta = t.append
fa = f.append
for value in iterable:
(ta if predicate(value) else fa)(value)
return (t, f)
Ответ 2
Вы можете использовать следующую функцию:
from itertools import filterfalse, tee
def fork(pred, iterable):
'Use a predicate to partition entries into false entries and true entries'
t1, t2 = tee(iterable)
return list(filterfalse(pred, t1)), list(filter(pred, t2))
Источник: itertools
Ответ 3
Полный код, следующий за предложением @jonrsharpe.
import itertools
def fork(iterable):
"Returns list of even, odd elements of a list"
t1, t2 = itertools.tee(iterable)
pred = lambda i: i % 2 == 0
return list(filter(pred, t2)), list(itertools.filterfalse(pred, t1))
odd, even = fork([1,2,3,4,5])
print(odd)
print(even)
Альтернативная версия numpy, которая может быть быстрее для больших массивов
import numpy as np
def fork(iterable):
"Returns array of even, odd elements of an array"
iterable_array = np.asarray(iterable)
mask = (iterable_array % 2 == 0)
return iterable_array[~mask], iterable_array[mask]
Ответ 4
Я ничего не нашел в стандартной библиотеке, выполняя то, что вы хотите. Я предлагаю вам эту пользовательскую реализацию, которая не оптимизирована вообще, но очень проста и удобна для чтения:
def myFunc(iterable, func):
first = [i for i in iterable if func(i)]
second = [i for i in iterable if not func(i)]
return first,second
numbers = [1, 2, 3, 4]
even_numbers, odd_numbers = myFunc(numbers, lambda x: x % 2 == 0)
print(even_numbers) # [2, 4]
print(odd_numbers) # [1, 3]
Ответ 5
Простейшая возможная реализация была бы, вероятно,
def partition(xs, cond):
res = [], []
for x in xs:
res[not cond(x)].append(x)
return res
Ответ 6
Вы можете создать свою собственную функцию:
l = [1, 2, 3, 4]
def fork(l,key):
return list(filter(key,l)), [i for i in l if i not in list(filter(key,l))]
even_numbers, odd_numbers = fork(l, lambda x: x % 2 == 0)
print(even_numbers)
print(odd_numbers)
Выход:
[2, 4]
[1, 3]