ここに誰かがPythonでreduce()関数を使用する便利なコードを持っていますか?例に見られる通常の+と*以外のコードはありますか?
GvRによるPython3000のreduce()の運命を参照してください
ここに誰かがPythonでreduce()関数を使用する便利なコードを持っていますか?例に見られる通常の+と*以外のコードはありますか?
GvRによるPython3000のreduce()の運命を参照してください
+ と * 以外に私が見つけた他の使用法は and と or でしたが、今ではこれらのケースを置き換えるためにany
andがあります。all
foldl
そしてfoldr
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)
reduce()
3 つ以上の数の最小公倍数を見つけるために使用できます。
#!/usr/bin/env python
from fractions import gcd
from functools import reduce
def lcm(*args):
return reduce(lambda a,b: a * b // gcd(a, b), args)
例:
>>> lcm(100, 23, 98)
112700
>>> lcm(*range(1, 20))
232792560
reduce()
ドット付きの名前を解決するために使用できます (使用するにeval()
は危険すぎます):
>>> import __main__
>>> reduce(getattr, "os.path.abspath".split('.'), __main__)
<function abspath at 0x009AB530>
与えられた N 個のリストの交点を見つける:
input_list = [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7]]
result = reduce(set.intersection, map(set, input_list))
戻り値:
result = set([3, 4, 5])
reduce はばかげたコマンドだと思います。したがって:
reduce(lambda hold,next:hold+chr(((ord(next.upper())-65)+13)%26+65),'znlorabggbbhfrshy','')
コードで見つけた使用法にはreduce
、論理式のクラス構造があり、これらの式オブジェクトのリストを式の結合に変換する必要がある状況が含まれていました。2 つの式が与えられたときに接続詞を作成する関数が既にあったmake_and
ので、 と書きreduce(make_and,l)
ました。(リストが空ではないことはわかっていました。そうでなければ、のようなものになっていたでしょうreduce(make_and,l,make_true)
。)
これはまさに、(一部の) 関数型プログラマーが好むreduce
(または関数が通常呼び出されるフォールド関数) 理由です。+
多くの場合、 、*
、min
、max
、連結、および私の場合は 、make_and
などのバイナリ関数が既に多く存在しmake_or
ます。を持つことで、reduce
これらの操作をリスト (またはツリーなど、一般的なフォールド関数の場合は何でも) に持ち上げることが簡単になります。
もちろん、特定のインスタンス化 ( などsum
) が頻繁に使用される場合は、 を書き続けたくありませんreduce
。ただし、sum
for ループで を定義する代わりに、で簡単に定義できますreduce
。
他の人が述べたように、読みやすさは確かに問題です。ただし、人々が「明確」でないと感じる唯一の理由reduce
は、多くの人が知っている機能や使用している機能ではないからだと主張することもできます。
次のように置き換えることができますvalue = json_obj['a']['b']['c']['d']['e']
。
value = reduce(dict.__getitem__, 'abcde', json_obj)
a/b/c/..
リストとしてパスが既にある場合。たとえば、リスト内のアイテムを使用して、ネストされた辞書の辞書の値を変更します。
@ブレア・コンラッド: 次のように、合計を使用して glob/reduce を実装することもできます。
files = sum([glob.glob(f) for f in args], [])
これは、2 つの例のどちらよりも冗長ではなく、完全に Pythonic であり、まだ 1 行のコードしかありません。
元の質問に答えるために、私は個人的に reduce の使用を避けようとしています。なぜなら、reduce は決して必要ではなく、他のアプローチよりも明確ではないからです。しかし、reduce に慣れて、リスト内包表記を好む人もいます (特に Haskell プログラマー)。しかし、reduce に関する問題についてまだ考えていないのであれば、おそらくそれを使用することについて心配する必要はありません。
言語の合成関数を書いているので、apply演算子と一緒にreduceを使用して合成関数を作成します。
一言で言えば、composeは、単一の関数に構成する関数のリストを取ります。段階的に適用される複雑な操作がある場合は、次のようにすべてをまとめます。
complexop = compose(stage4, stage3, stage2, stage1)
このようにして、次のような式に適用できます。
complexop(expression)
そして私はそれが以下と同等であることを望みます:
stage4(stage3(stage2(stage1(expression))))
さて、私の内部オブジェクトを構築するために、私はそれを言いたいです:
Lambda([Symbol('x')], Apply(stage4, Apply(stage3, Apply(stage2, Apply(stage1, Symbol('x'))))))
(Lambdaクラスはユーザー定義関数を構築し、Applyは関数アプリケーションを構築します。)
さて、残念ながら、折り目を間違った方向に折りたたむので、大まかに次のように使用しました。
reduce(lambda x,y: Apply(y, x), reversed(args + [Symbol('x')]))
何がreduceを生成するかを理解するには、REPLでこれらを試してください。
reduce(lambda x, y: (x, y), range(1, 11))
reduce(lambda x, y: (y, x), reversed(range(1, 11)))
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]])
最大3番目の要素+を持つリストであるため、[5、2、5、7]を返します。
これが目的かどうかはわかりませんが、Google でソース コードを検索できます。
Google コード検索で「function:reduce() lang:python」を検索するためのリンクをたどってください。
一見すると、次のプロジェクトが使用していますreduce()
などなど、しかし、これらは巨大なプロジェクトであるため、驚くことではありません。
reduce の機能は、Guido がより明示的だと思った関数再帰を使用して実行できます。
アップデート:
Google の Code Search は 2012 年 1 月 15 日に廃止されたため、通常の Google 検索に戻るだけでなく、Code Snippets Collectionと呼ばれる有望なものがあります。この (終了した) 質問の回答に、他の多くのリソースが記載されています Google Code Search の置き換えですか? .
更新 2 (2017 年 5 月 29 日):
Python の例 (オープンソース コード) の良いソースはNullege 検索エンジンです。
コードを grep した後、reduce を使用したのは階乗を計算することだけのようです。
reduce(operator.mul, xrange(1, x+1) or (1,))
Reduce はスカラー操作に限定されません。物をバケツに分類するためにも使用できます。(これは私が最も頻繁に reduce を使用するものです)。
オブジェクトのリストがあり、オブジェクトにフラットに格納されたプロパティに基づいて階層的に再編成したい場合を想像してください。次の例では、関数を使用して、XML でエンコードされた新聞の記事に関連するメタデータ オブジェクトのリストを生成しarticles
ます。articles
XML 要素のリストを生成し、それらを 1 つずつマップして、それらに関する興味深い情報を保持するオブジェクトを生成します。フロント エンドでは、ユーザーが記事をセクション/サブセクション/見出し別に閲覧できるようにしたいと考えています。その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 ループで実現できたかもしれませんが、関数型言語に真剣に時間を費やすと、map と reduce の観点から考えるようになる傾向があります。
ところで、設定しextract
たいプロパティの親がまだ存在しない可能性がある で行っているように、プロパティを設定するためのより良い方法を誰かが持っている場合は、お知らせください。
以前は、sqlalchemy-searchableの演算子を使用reduce
して PostgreSQL 検索ベクトルのリストを連結していました。||
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)
def dump(fname,iterable):
with open(fname,'w') as f:
reduce(lambda x, y: f.write(unicode(y,'utf-8')), iterable)
デリミタを削除せずに文字列を分割する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 で一般的な回答では処理されないエッジ ケースを処理することに注意してください。詳細な説明については、元のブログ投稿にリダイレクトしています。
ある種の重複間隔 (ゲノムエクソン) を表すオブジェクトがあり、__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 と 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))