Python 3.xでリストを返すmap()を取得する


523

リストを16進数にマップして、他の場所で使用しようとしています。Python 2.6では、これは簡単でした。

A: Python 2.6:

>>> map(chr, [66, 53, 0, 94])
['B', '5', '\x00', '^']

ただし、Python 3.1では、上記はマップオブジェクトを返します。

B: Python 3.1:

>>> map(chr, [66, 53, 0, 94])
<map object at 0x00AF5570>

Python 3.x で上記のAのように)マップされたリストを取得するにはどうすればよいですか?

または、これを行うより良い方法はありますか?私の最初のリストオブジェクトには約45の項目があり、それらを16進数に変換するIDが必要です。


2
リスト内包表記を使用する方がよりpythonic です。map()ほとんどの言語から削除リスト内包または上でそれを使用する理由はありませんので、forループが。
ボリス

回答:


771

これを行う:

list(map(chr,[66,53,0,94]))

Python 3+では、反復可能オブジェクトを反復処理する多くのプロセスが反復子自体を返します。ほとんどの場合、これによりメモリが節約され、処理が速くなります。

最終的にこのリストを反復処理するだけの場合は、リストに変換する必要さえありませんmap。次のようにオブジェクトを反復処理できるためです。

# Prints "ABCD"
for ch in map(chr,[65,66,67,68]):
    print(ch)

15
もちろん、これを反復することもできます:(chr(x)for x in [65,66,67,68])。地図も必要ありません。
hughdbrown 2009

2
@hughdbrown 3.1を使用するための引数はmap、複雑な関数、大きなデータセット、またはストリームで反復するときの遅延評価になります。
Andrew Keeton

18
@Andrewは実際にはHughが同じことを行うジェネレーターを理解しています 大括弧ではなく括弧に注意してください。
トリプティク

5
値がASCII / latin-1であることがわかっている場合の代替ソリューション(大量の入力の場合も高速)は、Cレイヤーで一括変換を行うことです。bytes(sequence_of_ints_in_range_0_to_256).decode('latin-1')これにより、str各要素のPython関数呼び出しを回避して、 Cレベルの関数呼び出しのみを使用するすべての要素。個々の文字listが本当に必要な場合は、上記をラップできますlistが、strすでに独自の文字の反復可能であるため、変更が必要なのは、可変性が必要な場合のみです。
ShadowRanger

1
list(map(str、[1,2,3]))は、CentOS 7のPython 3.4.3で「引数にエラーがあります」と表示します。リスト内包表記が機能します。
Andor 2016

108

Python 3.5の新機能:

[*map(chr, [66, 53, 0, 94])]

のおかげで 追加の開梱の汎化の

更新

常により短い方法を求めて、私はこれがうまくいくことを発見しました:

*map(chr, [66, 53, 0, 94]),

アンパックはタプルでも機能します。最後のコンマに注意してください。これにより、1要素のタプルになります。つまり、次と同等です。(*map(chr, [66, 53, 0, 94]),)

リスト括弧付きのバージョンからは1文字だけ短くなっていますが、アスタリスク(拡張構文)から始めるので、私の考えでは、書く方が良いです。:)


11
@Quelklef list()がきれいに見えない
Arijoon

5
@Quelklef:また、listコンストラクターを検索して一般的な関数呼び出し機構を呼び出す必要がないため、アンパックアプローチは非常に高速です。長い入力の場合は問題になりません。短いもののために、それは大きな違いを生むことができます。tuple繰り返し再構築されないように入力として上記のコードを使用すると、ipythonマイクロベンチマークは、list()ラッピングアプローチがアンパックよりも約20%長くかかることを示しています。心に留めておいてください。私たちは150 nsについて話しています。
ShadowRanger 2017年

古いものの何が問題でしたmapか?lmap新しいデフォルトでイテレータを返す場合は、新しい名前(?)を使用しますか?
ジョルジオ

1
*map()構文エラーが発生しPython 3.6ます:can't use starred expression here。あなたはそれを配置する必要がありますlist[ *map() ]
ALH

4
@ALHコマンドの最後のコンマを逃しました。間違えやすい!
LondonRob

103

なぜこれを行わないのですか?

[chr(x) for x in [66,53,0,94]]

これはリスト内包と呼ばれます。Googleでたくさんの情報を見つけることができますが、リスト内包表記に関するPython(2.6)ドキュメントへのリンクは次のとおりです。ただし、Python 3のドキュメントに興味があるかもしれません。


4
うーん。たぶん、リスト内包、ジェネレータ、map()、zip()、およびその他の多くのPythonの高速反復の良さに関する一般的な投稿が必要になるでしょう。
hughdbrown 09

46
より冗長なので、追加の変数を(2回)書き込む必要があると思います...操作がより複雑でラムダを書き込むことになる場合、またはいくつかの要素もドロップする必要がある場合は、理解力が決定的に優れていると思いますmap + filterよりも、適用したい関数がすでにある場合、mapはより簡潔です。
Fortran

1
+1:読みやすく、多くのパラメーターを持つ関数を使用できる
Le Droid

7
map(chr, [66,53,0,94])は間違いなくより簡潔です[chr(x) for x in [66,53,0,94]]
ジョルジオ

他の回答よりもはるかに高速
Evhz

25

リストを返すマップ機能には、特にインタラクティブセッション中の入力を節約できるという利点があります。リストを返すlmap関数を定義することができます(python2と同様にimap):

lmap = lambda func, *iterable: list(map(func, *iterable))

次に、lmapではなくを呼び出すmapと、ジョブが実行されます: lmap(str, x)よりも5文字(この場合は30%)list(map(str, x))短く、確かによりも短くなり[str(v) for v in x]ます。同様の関数を作成することもできfilterます。

元の質問にコメントがありました:

すべてのPython3バージョンに適用されるため、Python 3. *でリストを返すには、Getting map()に名前を変更することをお勧めします。これを行う方法はありますか?– meawoppl 1月24日17:58

それ可能ですが、非常に悪い考えです。ちょうど楽しみのために、ここにあなたができる方法があります(すべきではありません)。

__global_map = map #keep reference to the original map
lmap = lambda func, *iterable: list(__global_map(func, *iterable)) # using "map" here will cause infinite recursion
map = lmap
x = [1, 2, 3]
map(str, x) #test
map = __global_map #restore the original map and don't do that again
map(str, x) #iterator

4

古いコメントをより見やすくするために変換する:map完全に「これを行うためのより良い方法」として、入力がASCII序数であることがわかっている場合は、通常bytes、la に変換してデコードする方がはるかに高速bytes(list_of_ordinals).decode('ascii')です。これでstr値を取得できますが、list可変性などのためにが必要な場合は、それを変換するだけで済みます(さらに高速です)。たとえば、ipython45の入力を変換するマイクロベンチマークでは、次のようになります。

>>> %%timeit -r5 ordinals = list(range(45))
... list(map(chr, ordinals))
...
3.91 µs ± 60.2 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)

>>> %%timeit -r5 ordinals = list(range(45))
... [*map(chr, ordinals)]
...
3.84 µs ± 219 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)

>>> %%timeit -r5 ordinals = list(range(45))
... [*bytes(ordinals).decode('ascii')]
...
1.43 µs ± 49.7 ns per loop (mean ± std. dev. of 5 runs, 1000000 loops each)

>>> %%timeit -r5 ordinals = list(range(45))
... bytes(ordinals).decode('ascii')
...
781 ns ± 15.9 ns per loop (mean ± std. dev. of 5 runs, 1000000 loops each)

そのままにしておくとstr、最速のmapソリューションの約20%の時間がかかります。リストに戻しても、最速のmapソリューションの40%未満です。を介して一括変換しbytesbytes.decode次に一括変換してlist多くの作業を節約できます、前述のように、すべての入力がASCII序数(または文字ロケール固有のエンコーディングごとに1バイトの序数など)である場合にのみ機能しますlatin-1


2
list(map(chr, [66, 53, 0, 94]))

map(func、* iterables)->マップオブジェクト各反復可能オブジェクトの引数を使用して関数を計算する反復子を作成します。最短のイテラブルがなくなると停止します。

「イテレータを作る」

イテレータを返すことを意味します。

「各イテラブルの引数を使用して関数を計算します」

反復子のnext()関数は、各反復可能オブジェクトの値を1つ取り、それらのそれぞれを関数の1つの定位置パラメーターに渡します。

したがって、map()関数からイテレータを取得し、jsutをそれをlist()組み込み関数に渡すか、リスト内包表記を使用します。


2

上記の回答に加えてPython 3、我々は単純に作成することlistから結果値のをmapとして、

li = []
for x in map(chr,[66,53,0,94]):
    li.append(x)

print (li)
>>>['B', '5', '\x00', '^']

私が打たれた別の例で一般化するかもしれません、マップ上の操作もregex問題のように同様の方法で処理することができlistます、マップするアイテムを取得すると同時に結果セットを取得する関数を書くことができます。例

b = 'Strings: 1,072, Another String: 474 '
li = []
for x in map(int,map(int, re.findall('\d+', b))):
    li.append(x)

print (li)
>>>[1, 72, 474]

@miradulo Python 2ではリストが返されたはずですが、Python 3ではtypeだけが返され、同じ形式で指定しようとしました。あなたがそれが不必要だと思うなら、多分それが有用であると私が付け加えた理由であることができる私のような人々があるかもしれません。
Harry_pb

2
リスト内包表記、リスト関数、およびアンパック解答がすでにある場合、明示的なforループはIMHOをあまり追加しません。
miradulo、

1

オブジェクト内の各アイテムを反復して別の変数に格納するだけで、マップオブジェクトからリストを取得できます。

a = map(chr, [66, 53, 0, 94])
b = [item for item in a]
print(b)
>>>['B', '5', '\x00', '^']

0

Pythonのリスト内包表記と基本的なマップ関数ユーティリティを使用して、これを行うこともできます。

chi = [x for x in map(chr,[66,53,0,94])]


chiリストには、指定された要素のASIC値が含まれます。
darshan ks 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.