title用法 - python多个figure




使用reduce()的有用代码? (16)

有没有人在这里有任何有用的代码,在python中使用reduce()函数? 除了我们在例子中看到的通常的+和*以外是否还有其他代码?

通过GvR参考Python 3000中reduce()的命运


@Blair Conrad:你也可以实现你的glob / reduce使用总和,就像这样:

files = sum([glob.glob(f) for f in args], [])

这比你的两个例子中的任何一个都少冗长,完全是Pythonic,并且仍然只有一行代码。

因此,要回答原始问题,我个人尽量避免使用减少,因为它从来没有真正的必要,我发现它比其他方法不那么清晰。 然而,有些人习惯于减少并逐渐倾向于列出理解(特别是Haskell程序员)。 但是如果你还没有考虑减少问题,你可能不需要担心使用它。


reduce可以用来获得最大第n个元素的列表

reduce(lambda x,y: x if x[2] > y[2] else y,[[1,2,3,4],[5,2,5,7],[1,6,0,2]])

会返回[5,2,5,7],因为它是具有最大第三个元素+的列表


reduce()可用于解析虚线名称(其中eval()太不安全):

>>> import __main__
>>> reduce(getattr, "os.path.abspath".split('.'), __main__)
<function abspath at 0x009AB530>

reduce可以用来支持链式属性查找:

reduce(getattr, ('request', 'user', 'email'), self)

当然,这相当于

self.request.user.email

但是当你的代码需要接受一个任意的属性列表时它很有用。

(在处理Django模型时,任意长度的链式属性是很常见的。)


不确定这是否是您的想法,但您可以在Google上搜索源代码

在Google代码搜索上,按照链接搜索'function:reduce()lang:python'

乍一看,以下项目使用reduce()

  • MoinMoin的
  • Zope的
  • 数字
  • ScientificPython

等等等等,但这些都不足为奇,因为它们是巨大的项目。

Reduce的功能可以使用函数递归完成,我猜Guido认为它更加明确。

更新:

由于谷歌的代码搜索在2012年1月15日停止,除了恢复到常规谷歌搜索之外,还有一些称为代码片段收集的看起来很有前途的东西。 这个(封闭)问题的答案中提到了一些其他资源替换Google代码搜索?

更新2(2017年5月29日):

Nullege search engine是一个很好的Python示例源代码(在开源代码中)。


你可以将value = json_obj['a']['b']['c']['d']['e']替换为:

value = reduce(dict.__getitem__, 'abcde', json_obj)

如果您已将路径a/b/c/..列为列表。 例如, 使用列表中的项目更改嵌套字典的字典中的值 。


假设有一些年度统计数据存储在计数器列表中。 我们希望在不同年份的每个月中查找MIN / MAX值。 例如,1月份的数字为10,2月份的数字为15.我们需要将结果存储在新的Counter中。

from collections import Counter

stat2011 = Counter({"January": 12, "February": 20, "March": 50, "April": 70, "May": 15,
           "June": 35, "July": 30, "August": 15, "September": 20, "October": 60,
           "November": 13, "December": 50})

stat2012 = Counter({"January": 36, "February": 15, "March": 50, "April": 10, "May": 90,
           "June": 25, "July": 35, "August": 15, "September": 20, "October": 30,
           "November": 10, "December": 25})

stat2013 = Counter({"January": 10, "February": 60, "March": 90, "April": 10, "May": 80,
           "June": 50, "July": 30, "August": 15, "September": 20, "October": 75,
           "November": 60, "December": 15})

stat_list = [stat2011, stat2012, stat2013]

print reduce(lambda x, y: x & y, stat_list)     # MIN
print reduce(lambda x, y: x | y, stat_list)     # MAX

减少不限于标量操作; 它也可以用来把事物分成桶。 (这是我经常使用的减少)。

想象一下你有一个对象列表的情况,并且你希望根据平面存储在对象中的属性来分层重新组织它。 在下面的示例中,我使用articles函数生成了与XML编码的报纸中的articles相关的元数据对象列表。 articles生成一个XML元素列表,然后逐个映射它们,生成一些对象,这些对象包含一些关于它们的有趣信息。 在前端,我打算让用户按部分/子部分/标题浏览文章。 所以我使用reduce来获取文章列表并返回反映章节/子章节/文章层次结构的单个词典。

from lxml import etree
from Reader import Reader

class IssueReader(Reader):
    def articles(self):
        arts = self.q('//div3')  # inherited ... runs an xpath query against the issue
        subsection = etree.XPath('./ancestor::div2/@type')
        section = etree.XPath('./ancestor::div1/@type')
        header_text = etree.XPath('./head//text()')
        return map(lambda art: {
            'text_id': self.id,
            'path': self.getpath(art)[0],
            'subsection': (subsection(art)[0] or '[none]'),
            'section': (section(art)[0] or '[none]'),
            'headline': (''.join(header_text(art)) or '[none]')
        }, arts)

    def by_section(self):
        arts = self.articles()

        def extract(acc, art):  # acc for accumulator
            section = acc.get(art['section'], False)
            if section:
                subsection = acc.get(art['subsection'], False)
                if subsection:
                    subsection.append(art)
                else:
                    section[art['subsection']] = [art]
            else:
                acc[art['section']] = {art['subsection']: [art]}
            return acc

        return reduce(extract, arts, {})

我在这里给出了两个函数,因为我认为它显示了map和reduce在处理对象时可以很好地互补。 同样的事情可以用for循环来完成,但是用一种功能性语言花费一些时间,这会让我思考地图和缩小。

顺便说一下,如果有人有更好的方法来设置属性,例如我在extract做的属性,您想设置的属性的父母可能还不存在,请让我知道。


当需要查找类似set的对象序列的并set或交集时, reduce非常有用。

>>> reduce(operator.or_, ({1}, {1, 2}, {1, 3}))  # union
{1, 2, 3}
>>> reduce(operator.and_, ({1}, {1, 2}, {1, 3}))  # intersection
{1}

(除了实际的set ,这些的一个例子是Django的Q对象 。)

另一方面,如果你正在处理bool ,你应该使用anyall

>>> any((True, False, True))
True

我刚刚发现reduce有用用法: 拆分字符串而不删除分隔符该代码完全来自Programatically Speaking博客。 代码如下:

reduce(lambda acc, elem: acc[:-1] + [acc[-1] + elem] if elem == "\n" else acc + [elem], re.split("(\n)", "a\nb\nc\n"), [])

结果如下:

['a\n', 'b\n', 'c\n', '']

请注意,它处理SO中流行答案的边界情况。 有关更深入的解释,我将您重定向到原始博客文章。


我有一个使用reduce和glob模块构建要处理的文件列表的pipegrep的旧Python实现:

files = []
files.extend(reduce(lambda x, y: x + y, map(glob.glob, args)))

当时我发现它很方便,但它并不是必须的,因为类似的东西同样好,可能更具可读性

files = []
for f in args:
    files.extend(glob.glob(f))

我有代表某种重叠区间(基因组外显子)的对象,并使用__and__重新定义它们的交集:

class Exon:
    def __init__(self):
        ...
    def __and__(self,other):
        ...
        length = self.length + other.length  # (e.g.)
        return self.__class__(...length,...)

然后当我收集它们(例如,在同一个基因中)时,我使用它

intersection = reduce(lambda x,y: x&y, exons)

我用reduce 来连接一个PostgreSQL搜索向量列表和 || 在sqlalchemy可搜索的运算符:

vectors = (self.column_vector(getattr(self.table.c, column_name))
           for column_name in self.indexed_columns)
concatenated = reduce(lambda x, y: x.op('||')(y), vectors)
compiled = concatenated.compile(self.conn)

我认为减少是一个愚蠢的命令。 因此:

reduce(lambda hold,next:hold+chr(((ord(next.upper())-65)+13)%26+65),'znlorabggbbhfrshy','')

除了+和*以外,我发现的其他用途都是和和和,但现在我们有anyall来替代这些情况。

foldlfoldr确实出现在Scheme中...

这里有一些可爱的用法:

展开列表

目标:将[[1, 2, 3], [4, 5], [6, 7, 8]]变为[1, 2, 3, 4, 5, 6, 7, 8]

reduce(list.__add__, [[1, 2, 3], [4, 5], [6, 7, 8]], [])

数字列表中的数字

目标:将[1, 2, 3, 4, 5, 6, 7, 8]变成12345678

丑陋,缓慢的方式:

int("".join(map(str, [1,2,3,4,5,6,7,8])))

相当reduce方式:

reduce(lambda a,d: 10*a+d, [1,2,3,4,5,6,7,8], 0)

def dump(fname,iterable):
  with open(fname,'w') as f:
    reduce(lambda x, y: f.write(unicode(y,'utf-8')), iterable)




functional-programming