Python根据条件插入元素

Hyp*_*ino 5 python list

我试图根据条件创建一个列表,其中元素可能存在也可能不存在。例如,如果为 true,则列表为[1, 2, 3],否则为[1, 3]。目前,我可以做的是初始化列表并单独调用.insert.append元素,或者,我可以做类似的事情[1] + ([2] if condition else []) + [3],但这很丑陋。

我想知道是否有某种语法,例如[1, 2 if condition, 3],但我似乎找不到任何此类语法。有类似的语法吗?

编辑我的列表不是[1, 2, 3]。我想要一个适用于任何类型对象的通用解决方案,因为我什至不使用数字(这些是 WTForms 验证器)

fla*_*kes 7

我也习惯在 Perl 中使用以下模式执行此操作:

my @arr = (1, (condition? (2) : ()), 3);
Run Code Online (Sandbox Code Playgroud)

在Python中,您可以使用与 list 非常接近的解决方案来稍微接近这一点+,但使用*解包来避免许多其他数组:

arr = [1, *((2,) if condition else ()), 3]
Run Code Online (Sandbox Code Playgroud)

如果条件为真,可以使用一个产生值的助手来清理它。

T = TypeVar("T")

def cond(val: T, ok: bool) -> Iterable[T]:
    if ok:
        yield val

arr = [1, *cond(2, condition), 3]
Run Code Online (Sandbox Code Playgroud)

不过,这样做的缺点是不会短路,因此如果创建使用值的成本很高,您可能需要提供一个函数,而不是在条件为真时调用和返回的值。

另一种选择是在构建列表时使用哨兵值并对其进行过滤。可以将其与助手结合起来进行过滤。

class _Ignore: pass
IGNORE = _Ignore()

def cond_list(*elements: Union[T, _Ignore]) -> list[T]:
    return [e for e in elements if not isinstance(e, _Ignore)]


arr = cond_list(1, 2 if condition else IGNORE, 3)
Run Code Online (Sandbox Code Playgroud)

如果您想对结果容器类型保持灵活性,您可以选择返回一个可迭代的对象,并将其传递给容器构造函数:

def cond_iter(*elements: Union[T, _Ignore]) -> Iterable[T]:
    yield from (e for e in elements if not isinstance(e, _Ignore))


arr = set(cond_iter(1, 2 if condition else IGNORE, 3))
Run Code Online (Sandbox Code Playgroud)


mat*_*her 0

Is this what you're looking for?

[i for i in range(1,4) if i!=2]

UPDATE: based on nice answer above.

Making condition a function instead of a list will generalize it.

def condition(x):
    if(x==2):
        return False
    else:
        return True

[i for i in range(1,4) if condition(i)] 
Run Code Online (Sandbox Code Playgroud)