Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何更优雅地避免这种针对集合分组的单行reduce的黑客实现?_Python_Python 3.x - Fatal编程技术网

Python 如何更优雅地避免这种针对集合分组的单行reduce的黑客实现?

Python 如何更优雅地避免这种针对集合分组的单行reduce的黑客实现?,python,python-3.x,Python,Python 3.x,在年,我想出了一种方法,用一行(好的,单表达式)reduce来创建由许多其他语言(至少是Kotlin、ObjC、Swift、Smalltalk)定义的groupby的结果 我最初的尝试看起来像: def keyFunc(value): return derivative_of_value grouped = reduce( lambda accum, each: accum[keyFunc(each)].append(each), allValues, defa

在年,我想出了一种方法,用一行(好的,单表达式)
reduce
来创建由许多其他语言(至少是Kotlin、ObjC、Swift、Smalltalk)定义的
groupby
的结果

我最初的尝试看起来像:

def keyFunc(value):
    return derivative_of_value

grouped = reduce(
    lambda accum, each: accum[keyFunc(each)].append(each),
    allValues,
    defaultdict(list))
正如在我的旁白/切线中所述,问题在于lambda。lambda仅限于一个表达式。为了在reduce中工作,它必须返回一个修改后的累积参数

因此,我想出了以下方法,使用一个元组将dict引用从一个缩略移到另一个缩略,但也强制(忽略)更新同一dict的副作用:

from functools import reduce
grouped = reduce(
    lambda accum, each: (accum[0], accum[0][keyFunc(each)].append(each)),
    allValues,
    (defaultdict(list), None))[0]
问题是。。。有更好的办法吗给定我想要尝试的约束,并且仍然使用单个表达式reduce,而不使用一组辅助函数


(我知道有时候代码会告诉你一些事情,但我对这个案例感兴趣是因为学术方面的原因)

不知道为什么要用reduce甚至defaultdict来做这件事。但也有使用列表/听写理解的单行解决方案。例如,给定

>>> from collections import defaultdict
>>> def func1(a):
...     return str(a)
>>> b = list(range(10)) + list(range(5))
>>> b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
以下是dict的单线解决方案:

>>> {x: [y for y in b if func1(y) == x] for x in set([func1(z) for z in b])}
{'4': [4, 4], '5': [5], '2': [2, 2], '8': [8], '9': [9], '7': [7], '0': [0, 0], '3': [3, 3], '1': [1, 1], '6': [6]}

下面的解决方案完成了任务,但是很糟糕(正如@juanpa.arrivillaga在评论中指出的),因为您正在创建一个可能非常大的列表,然后立即将其丢弃。看

使用列表理解的多行解决方案(如果您计算defaultdict(列表)初始化行,则实际为两行)

例如,使用defaultdict

>>> a = defaultdict(list)
>>> [a[func1(x)].append(x) for x in b]
[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]
>>> a
defaultdict(<class 'list'>, {'0': [0, 0], '1': [1, 1], '2': [2, 2], '3': [3, 3], '4': [4, 4], '5': [5], '6': [6], '7': [7], '8': [8], '9': [9]})

[juanpa.arrivillaga]

不确定为什么要使用reduce甚至defaultdict来执行此操作。但也有使用列表/听写理解的单行解决方案。例如,给定

>>> from collections import defaultdict
>>> def func1(a):
...     return str(a)
>>> b = list(range(10)) + list(range(5))
>>> b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
以下是dict的单线解决方案:

>>> {x: [y for y in b if func1(y) == x] for x in set([func1(z) for z in b])}
{'4': [4, 4], '5': [5], '2': [2, 2], '8': [8], '9': [9], '7': [7], '0': [0, 0], '3': [3, 3], '1': [1, 1], '6': [6]}

下面的解决方案完成了任务,但是很糟糕(正如@juanpa.arrivillaga在评论中指出的),因为您正在创建一个可能非常大的列表,然后立即将其丢弃。看

使用列表理解的多行解决方案(如果您计算defaultdict(列表)初始化行,则实际为两行)

例如,使用defaultdict

>>> a = defaultdict(list)
>>> [a[func1(x)].append(x) for x in b]
[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]
>>> a
defaultdict(<class 'list'>, {'0': [0, 0], '1': [1, 1], '2': [2, 2], '3': [3, 3], '4': [4, 4], '5': [5], '6': [6], '7': [7], '8': [8], '9': [9]})

[juanpa.arrivillaga]

我将此信息发布到python邮件列表中,并收到了两个解决方案,这两个解决方案基本相同,但都是更优雅的改进:

grouped = reduce(
    lambda groups, each: groups[keyFunc(each)].append(each) or groups,
    allValues,
    defaultdict(list))
这使用
跳过执行实际工作的零件返回的
None
。真是谎言

grouped = reduce(
    lambda groups, each: (groups[keyFunc(each)].append(each), groups)[1],
    allValues,
    defaultdict(list))

第二个仍然使用元组,但仅将其分离到所需的程度,这样它就不会泄漏到代码的其余部分。

我将其发布到python邮件列表,并收到了两个解决方案,这两个解决方案基本相同,但都是更优雅的改进:

grouped = reduce(
    lambda groups, each: groups[keyFunc(each)].append(each) or groups,
    allValues,
    defaultdict(list))
这使用
跳过执行实际工作的零件返回的
None
。真是谎言

grouped = reduce(
    lambda groups, each: (groups[keyFunc(each)].append(each), groups)[1],
    allValues,
    defaultdict(list))

第二个仍然使用元组,但仅将其隔离到所需的程度,这样它就不会泄漏到代码的其余部分。

老实说,它甚至不可读,这确实是令人讨厌的:)提供了一个增强的
groupby
,基本用例不需要排序输入。这是一个terribe单行程序。您在
reduce
中使用了一个副作用,这是对函数构造的严重误用,IMO。只需在defaultdict中使用for循环即可。这是惯用的方式。如果要在单行中执行此操作,请定义一个函数并在单行中调用该函数。不要滥用功能结构。我们今天不是脾气暴躁吗Dhonestly,它甚至不可读,这确实是骇人和丑陋的:)提供了一个增强的
groupby
,它不需要基本用例的排序输入。这是一个terribe单行程序。您在
reduce
中使用了一个副作用,这是对函数构造的严重误用,IMO。只需在defaultdict中使用for循环即可。这是惯用的方式。如果要在单行中执行此操作,请定义一个函数并在单行中调用该函数。不要滥用功能结构。我们今天不是脾气暴躁吗有趣的傅。这些并没有真正使用reduce(),我最初的方法所希望的优点之一是尽可能少地调用keyFunc()。不过,使用理解在一行上做大量工作的有趣技巧是聪明的。我对“创建一个列表/字典”并不感到兴奋,只是为了消除它的副作用。但它启发了我做这件事:
any(a[func1(x)]。在b中为x添加(x)
这很聪明!它将每x调用一次keyFunc。不要在列表中使用副作用。这些并没有真正使用reduce(),我最初的方法所希望的优点之一是尽可能少地调用keyFunc()。不过,使用理解在一行上做大量工作的有趣技巧是聪明的。我对“创建一个列表/字典”并不感到兴奋,只是为了消除它的副作用。但它启发了我做这件事:
any(a[func1(x)]。在b中为x添加(x)
这很聪明!它将每x调用一次keyFunc。不要在列表中使用副作用