web-dev-qa-db-ja.com

マップ機能を理解する

map(function, iterable, ...)

Iterableのすべての項目に関数を適用し、結果の一覧を返します。追加の反復可能な引数が渡された場合、functionはその数の引数を取らなければならず、すべての反復可能要素からの項目に並列に適用されます。

あるイテラブルが他のイテラブルよりも短い場合は、None項目で拡張されていると見なされます。

FunctionがNoneの場合、恒等関数が仮定されます。複数の引数がある場合、map()はすべてのイテラブルからの対応する項目を含むタプルからなるリストを返します(一種の転置操作)。

反復可能な引数は、シーケンスまたは任意の反復可能オブジェクトです。結果は常にリストです。

これはデカルト積を作るのにどのような役割を果たしますか?

content = map(Tuple, array)

タプルをどこに置いても効果はありますか? map関数がなければ出力はabcであり、それがあればa, b, cです。

この機能を十分に理解したい。参照定義も理解しにくいです。派手な毛羽が多すぎる。

260
Web Master

mapは特にPythonicではありません。代わりにリスト内包表記を使用することをお勧めします。

map(f, iterable)

基本的に同等です:

[f(x) for x in iterable]

出力リストの長さは常に入力リストの長さと同じなので、map単独ではデカルト積を実行できません。リスト内包表記を使用してデカルト積を簡単に実行できます。

[(a, b) for a in iterable_a for b in iterable_b]

構文は少しわかりにくいです - それは基本的に以下と同等です:

result = []
for a in iterable_a:
    for b in iterable_b:
        result.append((a, b))
367
dave

mapはデカルト積にはまったく関係ありませんが、関数型プログラミングに精通している人がmapを使用して1を生成することを理解するのが不可能な方法を思いつく可能性があると思います。

Python 3のmapはこれと同じです。

def map(func, iterable):
    for i in iterable:
        yield func(i)

python 2の唯一の違いは、yieldingの代わりに一度に全部を返すように結果の完全なリストを作り上げることです。

Pythonの慣例では、特に最初の引数としてラムダ式を使用している場合は、mapの呼び出しと同じ結果を得るために、通常はリスト内包表記(またはジェネレータ式)が優先されます。

[func(i) for i in iterable]

「文字列を配列にする」という質問に対するコメントであなたが求めたものの例として、 'array'では、おそらくTupleかリストのどちらかが欲しいでしょう(どちらも他の言語の配列のように振舞います)。 -

 >>> a = "hello, world"
 >>> list(a)
['h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd']
>>> Tuple(a)
('h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd')

ここでmapを使用するのは、単一の文字列ではなく list で始まる場合です - mapはそれらすべてを個別にリスンできます。

>>> a = ["foo", "bar", "baz"]
>>> list(map(list, a))
[['f', 'o', 'o'], ['b', 'a', 'r'], ['b', 'a', 'z']]

map(list, a)はPython 2と同等ですが、Python 3ではlistループ(または反復が必要なだけでシーケンスを必要としないforのような処理関数)に渡す以外にsum呼び出しが必要です。 )しかし、リスト内包表記が通常は好ましいことにも注意してください。

>>> [list(b) for b in a]
[['f', 'o', 'o'], ['b', 'a', 'r'], ['b', 'a', 'z']]
79
lvc

mapは、ソースのすべての要素に関数を適用して新しいリストを作成します。

xs = [1, 2, 3]

# all of those are equivalent — the output is [2, 4, 6]
# 1. map
ys = map(lambda x: x * 2, xs)
# 2. list comprehension
ys = [x * 2 for x in xs]
# 3. explicit loop
ys = []
for x in xs:
    ys.append(x * 2)

n-ary mapは、入力イテラブルをまとめて圧縮し、その中間のzip形式のリストのすべての要素に変換関数を適用するのと同じです。デカルト積はnotです。

xs = [1, 2, 3]
ys = [2, 4, 6]

def f(x, y):
    return (x * 2, y // 2)

# output: [(2, 1), (4, 2), (6, 3)]
# 1. map
zs = map(f, xs, ys)
# 2. list comp
zs = [f(x, y) for x, y in Zip(xs, ys)]
# 3. explicit loop
zs = []
for x, y in Zip(xs, ys):
    zs.append(f(x, y))

ここではZipを使用しましたが、イテラブルが同じサイズでない場合、実際にはmapの動作はわずかに異なります - ドキュメントに記載されているように、Noneを含むようにイテラブルを拡張します。

31
Cat Plus Plus

簡単に言うと、map()が次のようなことをしていると想像できます。

def mymap(func, lst):
    result = []
    for e in lst:
        result.append(func(e))
    return result

ご覧のとおり、関数とリストを受け取り、入力リストの各要素に関数を適用した結果を含む新しいリストを返します。実際にはmap()複数 _ iterableを処理することができるので、「少し簡略化する」と述べました。

追加の反復可能な引数が渡される場合、functionはその数の引数を取らなければならず、すべての反復可能要素からの項目に並列に適用されます。あるイテラブルが他のイテラブルよりも短い場合は、None項目で拡張されていると見なされます。

質問の2番目の部分では、これはデカルト積を作成する際にどのような役割を果たしますか。さて、map()couldは、このようなリストのデカルト積を生成するために使用されます。

lst = [1, 2, 3, 4, 5]

from operator import add
reduce(add, map(lambda i: map(lambda j: (i, j), lst), lst))

...しかし、実を言うと、 product() を使用するのが、問題を解決するためのはるかに単純で自然な方法です。

from itertools import product
list(product(lst, lst))

どちらにしても、結果は上で定義されたようにlstのデカルト積になります。

[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5),
 (2, 1), (2, 2), (2, 3), (2, 4), (2, 5),
 (3, 1), (3, 2), (3, 3), (3, 4), (3, 5),
 (4, 1), (4, 2), (4, 3), (4, 4), (4, 5),
 (5, 1), (5, 2), (5, 3), (5, 4), (5, 5)]
20
Óscar López

map()関数は、リスト、ジェネレータ、文字列、その他のもののような反復可能なデータ構造の中のすべての項目に同じ手続きを適用するためにあります。

例を見てみましょう:map()はリストの中のすべての項目を繰り返し処理し、それぞれの項目に関数を適用することができます。それは新しいリストを返す(返す)よりもです。

数字を取り、その数字に1を加えてそれを返す関数があると想像してみてください。

def add_one(num):
  new_num = num + 1
  return new_num

数字のリストもあります。

my_list = [1, 3, 6, 7, 8, 10]

リスト内のすべての番号を増やしたい場合は、次のようにします。

>>> map(add_one, my_list)
[2, 4, 7, 8, 9, 11]

注:少なくともmap()は2つの引数を必要とします。 1つは関数名、もう1つはリストのようなものです。

map()ができる他の素晴らしいことを見てみましょう。 map()は複数のイテラブル(リスト、文字列など)を取り、各イテラブルから要素を引数として関数に渡すことができます。

3つのリストがあります。

list_one = [1, 2, 3, 4, 5]
list_two = [11, 12, 13, 14, 15]
list_three = [21, 22, 23, 24, 25]

map()はあなたに特定のインデックスで要素の追加を保持する新しいリストを作ることができます。

map()を覚えて、関数が必要です。今回は組み込みのsum()関数を使います。 map()を実行すると、以下の結果が得られます。

>>> map(sum, list_one, list_two, list_three)
[33, 36, 39, 42, 45]

メモ:
Python 2のmap()では、最も長いリストに従って(リストの要素をたどって)繰り返し、短いリストの場合はNoneを関数に渡します。したがって、関数はNoneを探して処理する必要があります。エラーになります。 Python 3では、map()は最短のリストで終わった後に停止します。また、Python 3では、map()はリストではなくイテレータを返します。

14
BlooB

Python3 - map(func、iterable)

(@BlooBはちょっとそれを述べたが)完全に言及されなかったことの一つはmapがマップオブジェクトNOTリストを返すことです。初期化と反復のパフォーマンスに関しては、これは大きな違いです。これら2つのテストを検討してください。

import time
def test1(iterable):
    a = time.clock()
    map(str, iterable)
    a = time.clock() - a

    b = time.clock()
    [ str(x) for x in iterable ]
    b = time.clock() - b

    print(a,b)


def test2(iterable):
    a = time.clock()
    [ x for x in map(str, iterable)]
    a = time.clock() - a

    b = time.clock()
    [ str(x) for x in iterable ]
    b = time.clock() - b

    print(a,b)


test1(range(2000000))  # Prints ~1.7e-5s   ~8s
test2(range(2000000))  # Prints ~9s        ~8s

ご覧のとおり、map関数の初期化にはほとんど時間がかかりません。ただし、マップオブジェクトを反復処理すると、単純に反復可能オブジェクトを反復処理するよりも時間がかかります。つまり、map()に渡された関数は、繰り返しで要素に到達するまで各要素に適用されません。リストが欲しいならリスト内包表記を使ってください。 forループで繰り返し処理する予定があり、途中で中断する場合は、mapを使用してください。

3
Ranga