通过python中的一些任意函数优雅地将列表(或字典)拆分为两个

Li *_*oyi 10 python select dictionary list-comprehension

是否有任何优雅的方法将列表/字典拆分为python中的两个列表/ dicts,接受一些任意的拆分函数?

我可以很容易地有两个列表推导,或两个选择,但在我看来应该有一些更好的方法来避免迭代每个元素两次.

我可以使用for循环和if语句轻松完成,但这需要7行代码,这应该是一个非常简单的操作.

有任何想法吗?

编辑:

仅供参考,我的两个解决方案是,

# given dict cows, mapping cow names to weight
# fast solution
fatcows = {}
thincows = {}
for name, weight in cows:
    if weight < 100:
        thincows[name] = weight
    else:
        fatcows[name] = weight

# double-list-comprehension solution would be
fatcows = {name: weight for name, weight in cows.items() if weight > 100}
thincows = {name: weight for name, weight in cows.items() if weight < 100}
Run Code Online (Sandbox Code Playgroud)

我当时认为必须有一些我从未想过的比这更优雅的东西,例如:

thincows, fatcows = ??? short expression involving cows ???
Run Code Online (Sandbox Code Playgroud)

我知道可以通过编写高阶函数来为我做这件事,我知道如何手动完成.我只是想知道是否有一些超级优雅的语言功能为我做这件事.

这就像你可以编写自己的子程序以及在列表上做SELECT的东西,或者你可以说

thincows = select(cows, lambda c: c.weight < 100)
Run Code Online (Sandbox Code Playgroud)

我希望有一些同样优雅的方式来分割列表,一次通过

sen*_*rle 6

3行怎么样?

fatcows, thincows = {}, {}
for name, weight in cows.items():
    (fatcows if weight > 50 else thincows)[name] = weight
Run Code Online (Sandbox Code Playgroud)

测试:

>>> cows = {'bessie':53, 'maud':22, 'annabel': 77, 'myrna':43 }
>>> fatcows, thincows = {}, {}
>>> for name, weight in cows.items():
...     (fatcows if weight > 50 else thincows)[name] = weight
... 
>>> fatcows
{'annabel': 77, 'bessie': 53}
>>> thincows
{'maud': 22, 'myrna': 43}
Run Code Online (Sandbox Code Playgroud)


Ada*_*eld 5

任何解决方案都需要花费O(N)时间进行计算,无论是通过两次通过列表,还是一次通过每个项目执行更多工作.最简单的方法就是使用您可以使用的工具:itertools.ifilteritertools.ifilterfalse:

def bifurcate(predicate, iterable):
    """Returns a tuple of two lists, the first of which contains all of the
       elements x of `iterable' for which predicate(x) is True, and the second
       of which contains all of the elements x of `iterable` for which
       predicate(x) is False."""
    return (itertools.ifilter(predicate, iterable),
            itertools.ifilterfalse(predicate, iterable))
Run Code Online (Sandbox Code Playgroud)


Ery*_*Sun 3

和牛一起玩更有趣:)

import random; random.seed(42)
cows = {n:random.randrange(50,150) for n in 'abcdefghijkl'}

thin = {}
for name, weight in cows.iteritems():
    thin.setdefault(weight < 100, {})[name] = weight

>>> thin[True]
{'c': 77, 'b': 52, 'd': 72, 'i': 92, 'h': 58, 'k': 71, 'j': 52}

>>> thin[False]
{'a': 113, 'e': 123, 'l': 100, 'g': 139, 'f': 117}
Run Code Online (Sandbox Code Playgroud)