Térkép (magasabb rendű funkció) - Map (higher-order function)
Sok programozási nyelvek , térkép a neve egy magasabb rendű függvény , amely érvényes a megadott függvény , hogy minden egyes eleme egy funktorhoz , például egy lista , visszatérve a találati listát ugyanabban a sorrendben. Gyakran alkalmazható mindennek, ha funkcionális formában tekintik .
A térkép fogalma nem korlátozódik a listákra: szekvenciális konténerekre , faszerű konténerekre, vagy akár absztrakt konténerekre, például határidős és ígéretes konténerekre vonatkozik .
Példák: lista feltérképezése
Tegyük fel, hogy van egy egész számok listája, [1, 2, 3, 4, 5]és ki szeretnénk számítani az egyes egészek négyzetét. Ehhez először definiálunk egy függvényt squareegyetlen számhoz (itt látható a Haskellben ):
square x = x * x
Utána hívhatunk
>>> map square [1, 2, 3, 4, 5]
amely azt eredményezi [1, 4, 9, 16, 25], hogy mapa teljes listán keresztülment, és squareminden elemre alkalmazta a függvényt .
Vizuális példa
Az alábbiakban megtekintheti a leképezési folyamat egyes lépéseinek nézetét azoknak az egész számoknak X = [0, 5, 8, 3, 2, 1]a listájához X', amelyeket a funkciónak megfelelően új listába szeretnénk leképezni :
A mapHaskell alap -előjátéka (azaz "standard könyvtár") része, és a következőképpen valósul meg:
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x : xs) = f x : map f xs
Általánosítás
Haskell -ben a polimorf függvényt map :: (a -> b) -> [a] -> [b] egy poltipikus függvényre általánosítják fmap :: Functor f => (a -> b) -> f a -> f b, amely minden típusosztályhoz tartozó típusra vonatkozik .
Functor
A típusú kivitelező listák []lehet meghatározni, mint egy példány a Functortípusú osztály alkalmazásával a mapfunkciót az előző példa:
instance Functor [] where
fmap = map
További példák a Functorfák:
-- a simple binary tree
data Tree a = Leaf a | Fork (Tree a) (Tree a)
instance Functor Tree where
fmap f (Leaf x) = Leaf (f x)
fmap f (Fork l r) = Fork (fmap f l) (fmap f r)
A fa hozamának feltérképezése:
>>> fmap square (Fork (Fork (Leaf 1) (Leaf 2)) (Fork (Leaf 3) (Leaf 4)))
Fork (Fork (Leaf 1) (Leaf 4)) (Fork (Leaf 9) (Leaf 16))
Minden esetben a Functortípusú osztály, fmapa szerződésben köteles engedelmeskedni funktorhoz törvények:
fmap id ≡ id -- identity law
fmap (f . g) ≡ fmap f . fmap g -- composition law
ahol a Haskell függvényösszetételét. jelöli .
Többek között ez lehetővé teszi elemi műveletek meghatározását különféle gyűjteményekhez .
Ezenkívül, ha F és G két functor, a természetes transzformáció a polimorf típusú függvény, amely tiszteletben tartja az fmap -t :
- bármilyen funkcióhoz .
Ha a h függvényt paraméteres polimorfizmus határozza meg, mint a fenti típusdefinícióban, akkor ez a specifikáció mindig teljesül.
Optimalizálás
A térképek matematikai alapja számos optimalizálást tesz lehetővé . Az összetételi törvény biztosítja mindkettőt
-
(map f . map g) listés map (f . g) list
ugyanarra az eredményre vezet; vagyis , . A második űrlapot azonban hatékonyabban lehet kiszámítani, mint az elsőt, mert mindegyikhez a teljes lista újratelepítése szükséges. Ezért a fordítók megpróbálják az első űrlapot a másodikra alakítani; Az ilyen típusú optimalizálási ismert térkép fúzió és a funkcionális analógja hurok fúzió .
map
A térképfüggvények olyan hajtogatással definiálhatók és gyakran definiálhatók, mint például foldr, ami azt jelenti, hogy egy térkép-hajtogatási fúziót lehet végezni : foldr f z . map gegyenértékű a következővel foldr (f . g) z.
A fenti térkép megvalósítása az egyedileg linkelt listákon nem farok-rekurzív , ezért sok keretet hozhat létre a veremben, ha nagy listával hívják meg. Sok nyelv felváltva biztosít "fordított térkép" funkciót, amely egyenértékű a leképezett lista megfordításával, de farok-rekurzív. Itt van egy megvalósítás, amely a fold -bal funkciót használja.
reverseMap f = foldl (\ys x -> f x : ys) []
Mivel az egyedileg linkelt lista megfordítása szintén farok-rekurzív, a fordított és a fordított térkép összeállítható a normál térkép farok-rekurzív módon történő végrehajtásához, bár a listán két áthaladást kell végrehajtani.
Nyelvi összehasonlítás
A térkép funkció funkcionális programozási nyelvekből származik.
A nyelv Lisp bevezetett egy térkép funkció az úgynevezett maplist1959-ben, némileg eltérő változatok már megjelent 1958-ban Ez az eredeti definíció maplist, és feltérképezi a funkció az egymást követő többi meg:
maplist[x;f] = [null[x] -> NIL;T -> cons[f[x];maplist[cdr[x];f]]]
A funkció maplisttovábbra is elérhető az újabb Lisps -ekben, például a Common Lisp -ben , bár a hasonló mapcarvagy az általánosabb funkciókat maprészesítenék előnyben.
Négyszögesítése eleme egy listát maplistlenne írva S-expresszió jelölést, mint ez:
(maplist (lambda (l) (sqr (car l))) '(1 2 3 4 5))
A függvény használatával a mapcarfenti példát így írnánk:
(mapcar (function sqr) '(1 2 3 4 5))
Ma mapping funkciókat támogatja (vagy meg lehet határozni) számos eljárási , objektum-orientált , és multi-paradigma nyelveken is: A C ++ 's Standard Library , ez az úgynevezett std::transform, a C # (3,0)' s LINQ könyvtár, hanem ún Select. A Térkép gyakran használt művelet olyan magas szintű nyelveken is, mint a ColdFusion Markup Language (CFML), a Perl , a Python és a Ruby ; a műveletet mapmind a négy nyelven hívják . A Ruby collectalias mapis rendelkezésre áll (a Smalltalk -tól ). A Common Lisp térképszerű funkciók családját biztosítja; az itt leírt viselkedésnek megfelelőt hívják mapcar(a -carhozzáférést a CAR művelet segítségével jelzi ). Vannak olyan szintaktikai konstrukciójú nyelvek is, amelyek ugyanazt a funkcionalitást nyújtják, mint a térkép funkció.
A térképet néha úgy általánosítják, hogy elfogadja a kétdimenziós (2-argumentus) függvényeket, amelyek a felhasználó által szolgáltatott függvényt két lista megfelelő elemeire tudják alkalmazni. Egyes nyelvek erre speciális neveket használnak, például map2 vagy zipWith . Nyelvek explicit variadic funkciók lehetnek változatai térkép változó argumentumainak száma a támogatás változó argumentumainak száma funkciókat. A 2 vagy több listát tartalmazó térkép kezelési problémával szembesül, ha a listák különböző hosszúságúak. Különböző nyelvek különböznek ebben. Néhányan kivételt emelnek. Néhányan megállnak a legrövidebb lista lejárta után, és figyelmen kívül hagyják a többi lista további elemeit. Néhányan folytatják a leghosszabb lista hosszát, és a már befejeződött listák esetében adjanak át néhány helyőrző értéket az értéket jelző függvénynek.
A nyelvek, amelyek támogatják az első osztályú funkciók és kikészítéséhez , maplehet részben alkalmazták , hogy szüntesse meg a funkciót, hogy a művek csak az egyik értéket egy elemenkénti egyenértékű, hogy a művek egy egész tartály; például map squareegy Haskell -függvény, amely négyzetbe zárja a lista egyes elemeit.
| Nyelv | Térkép | Térkép 2 listák | Térkép n listák | Megjegyzések | Különböző hosszúságú listák kezelése |
|---|---|---|---|---|---|
| APL |
func list
|
list1 func list2
|
func/ list1 list2 list3 list4
|
Az APL tömbfeldolgozó képességei implicitvé teszik a térképhez hasonló műveleteket | Hosszúság hiba, ha a lista hossza nem egyenlő vagy 1 |
| Közös Lisp |
(mapcar func list)
|
(mapcar func list1 list2)
|
(mapcar func list1 list2 ...)
|
megáll a legrövidebb lista hossza után | |
| C ++ |
std::transform(
|
std::transform(
|
A fejléc <algoritmus> kezdődik , vége , és eredményeként a bejárók miatt van írva kezdődően eredmény |
||
| C# |
ienum.Select(func)vagy A selectzáradék
|
ienum1.Zip(ienum2, func)
|
Selectegy kiterjesztési módszer A ienum egy IEnumerable van Zipbevezetve a .NET 4.0 -ban Hasonlóan minden .NET nyelvben |
a legrövidebb lista befejezése után leáll | |
| CFML |
obj.map(func)
|
Hol objvan tömb vagy szerkezet. funcérvként megkapja az egyes elemek értékét, indexét vagy kulcsát, valamint egy hivatkozást az eredeti objektumra.
|
|||
| Clojure |
(map func list)
|
(map func list1 list2)
|
(map func list1 list2 ...)
|
a legrövidebb lista befejezése után leáll | |
| D |
list.map!func
|
zip(list1, list2).map!func
|
zip(list1, list2, ...).map!func
|
A StoppingPolicy a zip -hez adta meg: a legrövidebb, a leghosszabb vagy a RequestSameLength | |
| Erlang |
lists:map(Fun, List)
|
lists:zipwith(Fun, List1, List2)
|
zipwith3 szintén elérhető
|
A listáknak azonos hosszúságúnak kell lenniük | |
| Elixír |
Enum.map(list, fun)
|
Enum.zip(list1, list2) |> Enum.map(fun)
|
List.zip([list1, list2, ...]) |> Enum.map(fun)
|
a legrövidebb lista befejezése után leáll | |
| F# |
List.map func list
|
List.map2 func list1 list2
|
Funkciók léteznek más típusokhoz is ( Seq és Array ) | Dob kivétel | |
| Groovy |
list.collect(func)
|
[list1 list2]
|
[list1 list2 ...]
|
||
| Haskell |
map func list
|
zipWith func list1 list2
|
zipWithn func list1 list2 ...
|
nmegfelel a listák számának; -ig előre definiáltzipWith7
|
a legrövidebb lista befejezése után leáll |
| Haxe |
array.map(func)
|
||||
| J |
func list
|
list1 func list2
|
func/ list1, list2, list3 ,: list4
|
J tömbfeldolgozó képességei implicitvé teszik a térképhez hasonló műveleteket | hosszúság hiba, ha a lista hossza nem egyenlő |
| Java 8+ |
stream.map(func)
|
||||
|
JavaScript 1.6 ECMAScript 5 |
array#map(func)
|
List1.map(function (elem1, i) {
|
List1.map(function (elem1, i) {
|
A#tömb térkép 3 érvet ad át a funcnak : az elemet, az elem indexét és a tömböt. A nem használt érvek elhagyhatók. | A List1 végén áll meg , szükség esetén a rövidebb tömböket meghatározatlan elemekkel bővíti . |
| Julia |
map(func, list)
|
map(func, list1, list2)
|
map(func, list1, list2, ..., listN)
|
HIBA: DimensionMismatch | |
| Logtalk |
map(Closure, List)
|
map(Closure, List1, List2)
|
map(Closure, List1, List2, List3, ...) (up to seven lists)
|
Csak a Bezárás érvet kell példányosítani. | Kudarc |
| Mathematica |
func /@ list
|
MapThread[func, {list1, list2}]
|
MapThread[func, {list1, list2, ...}]
|
A listáknak azonos hosszúságúnak kell lenniük | |
| Maxima |
map(f, expr1, ..., exprn)
|
a map egy olyan kifejezést ad vissza, amelynek vezető operátora megegyezik a kifejezésekével; maplist egy listát ad vissza |
|||
| OCaml |
List.map func list
|
List.map2 func list1 list2
|
Invalid_argument kivételt vet fel | ||
| PARI/GP |
apply(func, list)
|
N/A | |||
| Perl |
map block list
|
A blokk vagy exppr speciális $ _ változó sorban tartja a lista minden értékét. | A Helper List::MoreUtils::each_arraytöbb listát kombinál, amíg a leghosszabb kimerül, és megtölti a többitundef.
|
||
| PHP |
array_map(callable, array)
|
array_map(callable, array1,array2)
|
array_map(callable, array1,array2, ...)
|
A lehívható paraméterek számának meg kell egyeznie a tömbök számával. |
kiterjeszti a rövidebb listákat NULL elemekkel |
| Bevezető |
maplist(Cont, List1, List2).
|
maplist(Cont, List1, List2, List3).
|
maplist(Cont, List1, ...).
|
A lista argumentumai bemenet, kimenet vagy mindkettő. Subumes is zipWith, unzip, all | Csendes hiba (nem hiba) |
| Piton |
map(func, list)
|
map(func, list1, list2)
|
map(func, list1, list2, ...)
|
Visszaad egy listát a Python 2 -ben és egy iterátort a Python 3 -ban. |
zip()és map()(3.x) a legrövidebb lista befejezése után megáll, míg a map()(2.x) és itertools.zip_longest()(3.x) Noneelemekkel
bővíti a rövidebb listákat |
| Rubin |
enum.collect {block}
|
enum1.zip(enum2)
|
enum1.zip(enum2, ...)
|
enum is an Enumeration
|
megáll a meghívott objektum végén (az első lista); ha bármely más lista rövidebb, akkor nulla elemmel bővül |
| Rozsda |
list1.into_iter().map(func)
|
list1.into_iter().zip(list2).map(func)
|
a Iterator::mapés Iterator::zipmetódusok egyaránt átveszik az eredeti iterátor tulajdonjogát, és visszaadnak egy újat; a Iterator::zipmódszer belsőleg hívja be a IntoIterator::into_itermódszertlist2
|
a rövidebb lista befejezése után leáll | |
| S - R |
lapply(list, func)
|
mapply(func, list1, list2)
|
mapply(func, list1, list2, ...)
|
A rövidebb listák ciklusosak | |
| Scala |
list.map(func)
|
(list1, list2)
|
(list1, list2, list3)
|
Megjegyzés: 3 -nál több nem lehetséges. | a rövidebb lista befejezése után leáll |
| Rendszer (beleértve a csalást és az ütést ) |
(map func list)
|
(map func list1 list2)
|
(map func list1 list2 ...)
|
a listáknak azonos hosszúságúaknak kell lenniük (az SRFI-1 kiterjed a különböző hosszúságú listákra is) | |
| Csevej |
aCollection collect: aBlock
|
aCollection1 with: aCollection2 collect: aBlock
|
Nem sikerül | ||
| Szabványos ML |
map func list
|
ListPair.map func (list1, list2)
|
A 2 argumentumú térképeknél a func egy sorban veszi az érveit |
ListPair.mapleáll a legrövidebb lista befejezése után, míg kivételt
ListPair.mapEqokozUnequalLengths |
|
| Gyors |
sequence.map(func)
|
zip(sequence1, sequence2).map(func)
|
a legrövidebb lista befejezése után leáll | ||
|
XPath 3 XQuery 3 |
list ! blockfor-each(list, func)
|
for-each-pair(list1, list2, func)
|
A blockkontextusban az elem .az aktuális értéket tartalmazza
|
a legrövidebb lista befejezése után leáll |
Lásd még
- Funkció (funkcionális programozás)
- Konvolúció (informatika) , más néven konv vagy zip
- Szűrő (magasabb rendű funkció)
- Hajtogatás (magasabb rendű funkció)
- az egyes
- Szabad monoid
- Funkcionális programozás
- Magasabb rendű funkció
- A lista megértése
- Térkép (párhuzamos minta)