Szukaj…


Składnia

  • mapa (funkcja, iterowalna [, * dodatkowe_poznania])
  • future_builtins.map (funkcja, iterowalne [, * dodatkowe_poznania])
  • itertools.imap (funkcja, iterowalny [, * dodatkowe_poznania])

Parametry

Parametr Detale
funkcjonować funkcja mapowania (musi przyjmować tyle parametrów, ile jest iterowalnych) ( tylko pozycyjne )
iterowalne funkcja jest stosowana do każdego elementu iterowalnego ( tylko pozycyjnego )
* dodatkowe_podstawy zobacz iterowalne, ale tyle, ile chcesz ( opcjonalnie , tylko pozycja )

Uwagi

Wszystko, co można zrobić za pomocą map można również zrobić ze comprehensions :

list(map(abs, [-1,-2,-3]))    # [1, 2, 3]
[abs(i) for i in [-1,-2,-3]]  # [1, 2, 3]

Chociaż potrzebujesz zip jeśli masz wiele iteracji:

import operator
alist = [1,2,3]
list(map(operator.add, alist, alist))  # [2, 4, 6]
[i + j for i, j in zip(alist, alist)]  # [2, 4, 6]

Rozumienie listy jest wydajne i w wielu przypadkach może być szybsze niż map , więc przetestuj czasy obu podejść, jeśli prędkość jest dla Ciebie ważna.

Podstawowe użycie map, itertools.imap i future_builtins.map

Funkcja mapowania jest najprostsza spośród wbudowanych Pythona używanych do programowania funkcjonalnego. map() stosuje określoną funkcję do każdego elementu w iterowalnym:

names = ['Fred', 'Wilma', 'Barney']
Python 3.x 3.0
map(len, names)  # map in Python 3.x is a class; its instances are iterable
# Out: <map object at 0x00000198B32E2CF8>

map zgodna z Python 3 znajduje się w module future_builtins :

Python 2.x 2.6
from future_builtins import map  # contains a Python 3.x compatible map()
map(len, names)                  # see below
# Out: <itertools.imap instance at 0x3eb0a20>

Alternatywnie, w Pythonie 2 można użyć imap z itertools aby uzyskać generator

Python 2.x 2.3
map(len, names)   # map() returns a list
# Out: [4, 5, 6]

from itertools import imap
imap(len, names)  # itertools.imap() returns a generator
# Out: <itertools.imap at 0x405ea20>

Wynik można jawnie przekonwertować na list aby usunąć różnice między Pythonem 2 i 3:

list(map(len, names))
# Out: [4, 5, 6]

map() można zastąpić równoważnym zrozumieniem listy lub wyrażeniem generatora :

[len(item) for item in names] # equivalent to Python 2.x map()
# Out: [4, 5, 6]

(len(item) for item in names) # equivalent to Python 3.x map()
# Out: <generator object <genexpr> at 0x00000195888D5FC0>

Mapowanie każdej wartości w iterowalnym

Na przykład możesz wziąć wartość bezwzględną każdego elementu:

list(map(abs, (1, -1, 2, -2, 3, -3))) # the call to `list` is unnecessary in 2.x
# Out: [1, 1, 2, 2, 3, 3]

Anonimowa funkcja obsługuje również mapowanie listy:

map(lambda x:x*2, [1, 2, 3, 4, 5])
# Out: [2, 4, 6, 8, 10]

lub konwertując wartości dziesiętne na wartości procentowe:

def to_percent(num):
    return num * 100

list(map(to_percent, [0.95, 0.75, 1.01, 0.1]))
# Out: [95.0, 75.0, 101.0, 10.0]

lub przeliczając dolary na euro (biorąc pod uwagę kurs wymiany):

from functools import partial
from operator import mul

rate = 0.9  # fictitious exchange rate, 1 dollar = 0.9 euros
dollars = {'under_my_bed': 1000,
           'jeans': 45,
           'bank': 5000}

sum(map(partial(mul, rate), dollars.values()))
# Out: 5440.5

functools.partial to wygodny sposób na ustalenie parametrów funkcji, dzięki czemu można ich używać z map zamiast z wykorzystaniem lambda lub tworzenia niestandardowych funkcji.

Wartości mapowania różnych iteracji

Na przykład obliczanie średniej każdego i elementu wielu iteracji:

def average(*args):
    return float(sum(args)) / len(args)  # cast to float - only mandatory for python 2.x

measurement1 = [100, 111, 99, 97]
measurement2 = [102, 117, 91, 102]
measurement3 = [104, 102, 95, 101]

list(map(average, measurement1, measurement2, measurement3))
# Out: [102.0, 110.0, 95.0, 100.0]

Istnieją różne wymagania, jeśli więcej niż jedna iterowalna jest przekazywana do map zależności od wersji Pythona:

  • Funkcja musi przyjmować tyle parametrów, ile jest iterowalnych:

    def median_of_three(a, b, c):
        return sorted((a, b, c))[1]
    
    list(map(median_of_three, measurement1, measurement2))
    

    TypeError: median_of_three () brakuje 1 wymaganego argumentu pozycyjnego: „c”

    list(map(median_of_three, measurement1, measurement2, measurement3, measurement3))
    

    TypeError: median_of_three () przyjmuje 3 argumenty pozycyjne, ale podano 4

Python 2.x 2.0.1
  • map : mapowanie iteruje tak długo, jak jedna iterowalna nadal nie jest w pełni wykorzystana, ale zakłada, że None z w pełni wykorzystanych iteracji:

    import operator
    
    measurement1 = [100, 111, 99, 97]
    measurement2 = [102, 117]
    
    # Calculate difference between elements
    list(map(operator.sub, measurement1, measurement2))
    

    TypeError: nieobsługiwane typy operandów dla -: „int” i „NoneType”

  • itertools.imap i future_builtins.map : Mapowanie zatrzymuje się, gdy tylko jeden iterowalny zatrzymuje się:

    import operator
    from itertools import imap
    
    measurement1 = [100, 111, 99, 97]
    measurement2 = [102, 117]
    
    # Calculate difference between elements
    list(imap(operator.sub, measurement1, measurement2))
    # Out: [-2, -6]
    list(imap(operator.sub, measurement2, measurement1))
    # Out: [2, 6]
    
Python 3.x 3.0.0
  • Mapowanie kończy się, gdy tylko jeden iterowalny zatrzymuje się:

    import operator
    
    measurement1 = [100, 111, 99, 97]
    measurement2 = [102, 117]
    
    # Calculate difference between elements
    list(map(operator.sub, measurement1, measurement2))
    # Out: [-2, -6]
    list(map(operator.sub, measurement2, measurement1))
    # Out: [2, 6]
    

Transponowanie za pomocą mapy: użycie „Brak” jako argumentu funkcji (tylko python 2.x)

from itertools import imap
from future_builtins import map as fmap # Different name to highlight differences

image = [[1, 2, 3],
         [4, 5, 6],
         [7, 8, 9]]

list(map(None, *image))
# Out: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
list(fmap(None, *image))
# Out: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
list(imap(None, *image))
# Out: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

image2 = [[1, 2, 3],
          [4, 5],
          [7, 8, 9]]
list(map(None, *image2))
# Out: [(1, 4, 7), (2, 5, 8), (3, None, 9)]  # Fill missing values with None
list(fmap(None, *image2))
# Out: [(1, 4, 7), (2, 5, 8)]                # ignore columns with missing values
list(imap(None, *image2))
# Out: [(1, 4, 7), (2, 5, 8)]                # dito
Python 3.x 3.0.0
list(map(None, *image))

TypeError: Obiekt „NoneType” nie jest wywoływalny

Ale istnieje obejście mające na celu uzyskanie podobnych wyników:

def conv_to_list(*args):
    return list(args)

list(map(conv_to_list, *image))
# Out: [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Mapowanie szeregowe i równoległe

map () to wbudowana funkcja, co oznacza, że jest dostępna wszędzie bez potrzeby używania instrukcji „import”. Jest dostępny wszędzie tak jak print (). Jeśli spojrzysz na przykład 5, zobaczysz, że musiałem użyć instrukcji importu, zanim mogłem użyć ładnego wydruku (import pprint). Dlatego pprint nie jest funkcją wbudowaną

Mapowanie serii

W takim przypadku każdy argument iterowalny jest dostarczany jako argument funkcji mapującej w porządku rosnącym. Powstaje, gdy mamy tylko jedną iterowalną mapę, a funkcja mapowania wymaga jednego argumentu.

Przykład 1

insects = ['fly', 'ant', 'beetle', 'cankerworm']
f = lambda x: x + ' is an insect'
print(list(map(f, insects))) # the function defined by f is executed on each item of the iterable insects

prowadzi do

['fly is an insect', 'ant is an insect', 'beetle is an insect', 'cankerworm is an insect']

Przykład 2

print(list(map(len, insects))) # the len function is executed each item in the insect list

prowadzi do

[3, 3, 6, 10]

Równoległe mapowanie

W tym przypadku każdy argument funkcji mapowania jest pobierany równolegle ze wszystkich iteracji (po jednym z każdej iterowalnej). Tak więc liczba dostarczonych iteracji musi być zgodna z liczbą argumentów wymaganych przez funkcję.

carnivores = ['lion', 'tiger', 'leopard', 'arctic fox']
herbivores = ['african buffalo', 'moose', 'okapi', 'parakeet']
omnivores = ['chicken', 'dove', 'mouse', 'pig']

def animals(w, x, y, z):
    return '{0}, {1}, {2}, and {3} ARE ALL ANIMALS'.format(w.title(), x, y, z)

Przykład 3

# Too many arguments
# observe here that map is trying to pass one item each from each of the four iterables to len. This leads len to complain that
# it is being fed too many arguments
print(list(map(len, insects, carnivores, herbivores, omnivores)))

prowadzi do

TypeError: len() takes exactly one argument (4 given)

Przykład 4

# Too few arguments
# observe here that map is suppose to execute animal on individual elements of insects one-by-one. But animals complain when
# it only gets one argument, whereas it was expecting four.
print(list(map(animals, insects)))

prowadzi do

TypeError: animals() missing 3 required positional arguments: 'x', 'y', and 'z'

Przykład 5

# here map supplies w, x, y, z with one value from across the list
import pprint
pprint.pprint(list(map(animals, insects, carnivores, herbivores, omnivores)))

prowadzi do

 ['Fly, lion, african buffalo, and chicken ARE ALL ANIMALS',
 'Ant, tiger, moose, and dove ARE ALL ANIMALS',
 'Beetle, leopard, okapi, and mouse ARE ALL ANIMALS',
 'Cankerworm, arctic fox, parakeet, and pig ARE ALL ANIMALS']


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow