जावास्क्रिप्ट में कोई Array.prototype.flatMap क्यों नहीं?


82

flatMapसंग्रह पर अविश्वसनीय रूप से उपयोगी है, लेकिन जावास्क्रिप्ट एक होने के दौरान प्रदान नहीं करता है Array.prototype.map। क्यों?

वहाँ flatMapआसान और कुशल दोनों तरह से जावास्क्रिप्ट में अनुकरण करने का कोई तरीका w / o flatMapमैन्युअल रूप से परिभाषित कर रहा है ?


10
"क्यों?" क्योंकि किसी ने अभी तक कोई प्रस्ताव नहीं किया? यहाँ एक नई सुविधा का प्रस्ताव करने का तरीका बताया गया है"क्या फ़्लैटमैप का अनुकरण करने का कोई तरीका है ... डब्ल्यू / ओ मैन्युअल रूप से फ़्लैटमैप को परिभाषित कर रहा है?" उह? मुझे समझ नहीं आ रहा है। तुम्हारा मतलब है arr.reduce((arr, v) => (arr.push(...v), arr), [])?
फेलिक्स क्लिंग

(^ यह केवल चपटा हिस्सा है, इसलिए मुझे लगता है कि यह होना चाहिए arr.map(...).reduce(...))।
फेलिक्स क्लिंग

आप इसे पिंग करने के बाद सरणी को समतल कर सकते हैं .map
kennytm

1
हम्म, आप इसे "एमुलेट" करना चाहते हैं लेकिन इसे "परिभाषित" नहीं करना चाहते। इसका क्या मतलब हो सकता है?

8
यह जल्द ही जेएस का हिस्सा बनने जा रहा है। tc39.github.io/proposal-flatMap
विजयेंद्रन

जवाबों:


99

अपडेट: Array.prototype.flatMap इसे ES2019 में बनाया

यह कई वातावरणों में व्यापक रूप से समर्थित है। नीचे दिए गए स्निपेट का उपयोग करके देखें कि क्या यह आपके ब्राउज़र में काम करता है -

const data =
  [ 1, 2, 3, 4 ]
  
console.log(data.flatMap(x => Array(x).fill(x)))
// [ 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 ]


"जावास्क्रिप्ट में कोई Array.prototype.flatMap क्यों नहीं?"

क्योंकि प्रोग्रामिंग जादू नहीं है और हर भाषा में ऐसी विशेषताएं / प्रधानताएँ नहीं हैं जो हर दूसरी भाषा में होती हैं। क्या मायने रखता है जावास्क्रिप्ट आपको इसे अपने दम पर परिभाषित करने की क्षमता देता है -

const concat = (x,y) =>
  x.concat(y)

const flatMap = (f,xs) =>
  xs.map(f).reduce(concat, [])

const xs = [1,2,3]

console.log(flatMap(x => [x-1, x, x+1], xs))

या फिर से लिखना जो दो छोरों को एक में समेट देता है -

const flatMap = (f, xs) =>
  xs.reduce((r, x) => r.concat(f(x)), [])

const xs = [1,2,3]

console.log(flatMap(x => [x-1, x, x+1], xs))

यदि आप चाहते हैं कि इसका विस्तार हो Array.prototype, तो कुछ भी आपको रोक नहीं रहा है -

if (!Array.prototype.flatMap) {
  function flatMap (f, ctx) {
    return this.reduce
      ( (r, x, i, a) =>
          r.concat(f.call(ctx, x, i, a))
      , []
      )
  }
  Array.prototype.flatMap = flatMap
}

const ranks =
  [ 'J', 'Q', 'K', 'A' ]
  
const suits =
  [ '♡', '♢', '♤', '♧' ]

const result =
  ranks.flatMap(r =>
    suits.flatMap(s =>
      [[r, s]]
    )
  )

console.log(JSON.stringify(result))
// [ ['J','♡'], ['J','♢'], ['J','♤'], ['J','♧']
// , ['Q','♡'], ['Q','♢'], ['Q','♤'], ['Q','♧']
// , ['K','♡'], ['K','♢'], ['K','♤'], ['K','♧']
// , ['A','♡'], ['A','♢'], ['A','♤'], ['A','♧']
// ]


1
इसे Array.prototype._mylib_flatMapकेवल परिभाषित करने के बजाय प्रोटोटाइप (जैसे ), या ईएस 6 प्रतीकों का बेहतर उपयोग करने के लिए किसी भी जोड़ को नाम देना बेहतर माना जाता है Array.prototype.flatMap
फेंगयांग वांग

11
@FengyangWang "बेहतर माना जाता है" अत्यधिक व्यक्तिपरक है। यदि यह आपका अपना ऐप है और आपके पास अपने प्रोटोटाइप को बढ़ाने का एक कारण है, तो इसमें कुछ भी गलत नहीं है। यदि यह एक पुस्तकालय / मॉड्यूल / ढांचा है जिसे आप दूसरों के उपयोग के लिए वितरित कर रहे हैं, तो मैं आपसे सहमत हूं। टिप्पणियाँ हालांकि इस पर चर्चा करने के लिए जगह नहीं हैं - यह मामला टिप्पणियों में प्रदान किए जाने की तुलना में अधिक स्पष्टीकरण और विवरण का हकदार है।
धन्यवाद

सबसे पहले बदसूरत है: फलाव के रूप में परिभाषित फ्लैटपाइप कोड को गड़बड़ा देगा - mapवैश्विक फ़ंक्शन के रूप में परिभाषित कार्यात्मक कोड की कल्पना करें ! दूसरा सिर्फ बुरा अभ्यास है
सेर्गेई अलाव

3
@SergeyAlaev re: "एक वैश्विक कार्य के रूप में मानचित्र की कल्पना करें" हाहा मैं अपने उपयोगिता कार्यों के बहुत सारे काम करता हूं। मैं उन्हें तीर फ़ंक्शंस के सीक्वेंस का उपयोग करके भी करी। "अग्ली" व्यक्तिपरक है। और आपने अपने "बुरे अभ्यास" टिप्पणी का समर्थन करने के लिए कोई तर्क नहीं दिया है। आपकी टिप्पणी मुझे इंगित करती है कि आपके पास कार्यात्मक प्रोग्रामिंग के साथ बहुत कम अनुभव है। हास्केल जैसी भाषा लें जहां प्रस्तावना में "ग्लोबल्स" के ढेर शामिल हैं ... कोई भी यह नहीं कह रहा है कि यह "बदसूरत" या "बुरा व्यवहार" है। आप अभी इससे परिचित नहीं हैं।
धन्यवाद

5
@SergeyAlaev या पर विचार रैकेट है append, map, filter, foldl, foldrडिफ़ॉल्ट नाम स्थान में अनगिनत दूसरों के बीच में। यह इसे एक बुरा अभ्यास नहीं बनाता है क्योंकि आपने किसी को "ग्लोबल्स खराब हैं" या "फैले हुए मूल निवासी बुरा है" कहते हुए सुना - रैकेट सबसे अच्छी डिज़ाइन की गई भाषाओं में से है। आपको बस यह नहीं पता कि इसे कब / कैसे उचित तरीके से करना है।
धन्यवाद

48

flatMapES2019 (ES10) के भाग के रूप में TC39 द्वारा अनुमोदित किया गया है। आप इसे इस तरह से उपयोग कर सकते हैं:

[1, 3].flatMap(x => [x, x + 1]) // > [1, 2, 3, 4]

यहाँ विधि का अपना कार्यान्वयन है:

const flatMap = (f, arr) => arr.reduce((x, y) => [...x, ...f(y)], [])

फ्लैटपैन पर एमडीएन आर्टिकल


विशेष रूप से, MDN के अनुसार आधिकारिक तौर पर नोड 11.0.0 में फ्लैप मैप है: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
कार्ल वॉल्श

3
@CarlWalsh मुझे खेद है, मैं विरोध नहीं कर सकता। बिल्ली क्या है flapMap? मैं अपने नक्शे को समतल करना चाहता हूं, इसे फ्लैप नहीं करना चाहता हूं!
एरिक

एक और विषय पर, यह अंत में जावास्क्रिप्ट सरणी के बदल जाता है monads में ™ ️ 🙃
Kutyel

यह एक पुराना उत्तर है लेकिन यह काफी अक्षम है, विशेष रूप से बड़े सरणियों पर (एक नया सरणी बनाता है और प्रत्येक पुनरावृत्ति पर सभी पिछले तत्व को कॉपी करता है)। एक अन्य तरीका है, कॉनकट का उपयोग करना const flatMap = (arr, ...args) => [].concat(...arr.map(...args));(या applyयदि आप फैलाने वाले ऑपरेटर का उपयोग नहीं कर सकते हैं) का उपयोग करना - हालांकि इस कॉनकट संस्करण में भारी सरणियों के लिए स्टैक आकार के मुद्दे हैं जैसा कि एक समाधान में उल्लेख किया गया है
बाली बालो

10

मुझे पता है कि आपने कहा था कि आप इसे स्वयं परिभाषित नहीं करना चाहते हैं, लेकिन यह कार्यान्वयन एक बहुत ही तुच्छ परिभाषा है।

वहाँ भी इसी github पृष्ठ से है:

यहाँ es6 स्प्रेड का उपयोग करने का थोड़ा सा तरीका है, renaudtertrais की - के समान, लेकिन es6 का उपयोग करना और प्रोटोटाइप में जोड़ना नहीं।

var flatMap = (a, cb) => [].concat(...a.map(cb))

const s = (v) => v.split(',')
const arr = ['cat,dog', 'fish,bird']

flatMap(arr, s)

क्या इनमें से कोई मदद करेगा?

यह ध्यान दिया जाना चाहिए (@ftor के लिए धन्यवाद) कि यह उत्तरार्द्ध "समाधान" "अधिकतम कॉल स्टैक आकार से अधिक" से ग्रस्त है अगर वास्तव में बड़े (जैसे, 300k तत्व) सरणी पर कहा जाता है a


2
यह कार्यान्वयन बड़े सरणियों के लिए स्टैक को उड़ा सकता है।

बस स्पष्ट होने के लिए, अगर मैं आपको सही ढंग से समझता हूं, @ आफ्टर, आप मेरे द्वारा दिए गए लिंक में पुनरावर्ती कार्यान्वयन के बारे में बात कर रहे हैं, न कि मैं अपने उत्तर के अंत में कोड ब्लॉक में दिखाऊं, है ना?
एलन मीम्स

2
कोशिश करो [].concat(...(new Array(300000).fill("foo").map(x => x.toUpperCase())))। यकीन है, यह एक कोने का मामला है। लेकिन आपको कम से कम इसका उल्लेख करना चाहिए।

धन्यवाद। मैंने इस आशय में एक नोट जोड़ा।
एलन मीम्स

7

लॉडश एक फ्लैटमैप फ़ंक्शन प्रदान करता है, जो मुझे व्यावहारिक रूप से जावास्क्रिप्ट के समान है जो इसे मूल रूप से प्रदान करता है। यदि आप एक लॉडश उपयोगकर्ता नहीं हैं, तो ES6 की Array.reduce()विधि आपको एक ही परिणाम दे सकती है, लेकिन आपको असतत चरणों में मैप करना होगा।

नीचे प्रत्येक विधि का एक उदाहरण है, पूर्णांकों की सूची को मैप करना और केवल बाधाओं को वापस करना।

लोदाश:

_.flatMap([1,2,3,4,5], i => i%2 !== 0 ? [i] : [])

ES6 कम करें:

[1,2,3,4,5].map(i => i%2 !== 0 ? [i] : []).reduce( (a,b) => a.concat(b), [] )


1

मैंने कुछ इस तरह किया:

Array.prototype.flatMap = function(selector){ 
  return this.reduce((prev, next) => 
    (/*first*/ selector(prev) || /*all after first*/ prev).concat(selector(next))) 
}

[[1,2,3],[4,5,6],[7,8,9]].flatMap(i => i); //[1, 2, 3, 4, 5, 6, 7, 8, 9]

[{subarr:[1,2,3]},{subarr:[4,5,6]},{subarr:[7,8,9]}].flatMap(i => i.subarr); //[1, 2, 3, 4, 5, 6, 7, 8, 9]


हाय सेरही, मैंने इस कोड की कोशिश की है, जब माता-पिता केवल एक वस्तु अप्रत्याशित परिणाम देंगे। `` `Array.prototype.flatMap = function (चयनकर्ता) {if (यह .length == 1) {वापसी चयनकर्ता (यह [0]); } यह वापस लौटाएं। पृष्ठ पर जाएं ((मौजूदा, अगला) => (/ * पहला * / चयनकर्ता (मौजूदा) || / * सभी के बाद पहले * / prev) .concat (चयनकर्ता (अगला)))}; `` `
जॉनी

0

हम अब flatMap()जावास्क्रिप्ट में हैं! और यह बहुत अच्छी तरह से समर्थित है

फ्लैटपाइप () विधि पहले मैपिंग फ़ंक्शन का उपयोग करके प्रत्येक तत्व को मैप करती है, फिर परिणाम को नए सरणी में समतल करती है। यह एक मानचित्र () के समान है, इसके बाद एक फ्लैट () गहराई 1 है

const dublicate = x => [x, x];

console.log([1, 2, 3].flatMap(dublicate))


पोस्ट कोड को चलाते समय त्रुटि हो रही है{ "message": "Uncaught TypeError: [1,2,3].flatMap is not a function", "filename": "https://stacksnippets.net/js", "lineno": 15, "colno": 23 }
SolutionMill

आप किस ब्रोसर का उपयोग कर रहे हैं? एज, IE और सैमसंग इंटरनेट अभी तक इसका समर्थन नहीं करता है, Youg, Edge जल्द ही V8 पर चलेगा। तो उन का समर्थन करने के लिए, आप एक polyfil का उपयोग कर सकते हैं
bigInt

क्रोम संस्करण 67.0.3396.87 (आधिकारिक बिल्ड) (64-बिट)
SolutionMill

आपका ब्राउज़र पुराना है .. आपको इसे अपडेट करना चाहिए या स्वचालित रूप से अपडेट करने के लिए सेट करना चाहिए।
बिगइंट

0

Array.prototype.flatMap()अब जेएस में आ गया है। हालांकि, सभी ब्राउज़र वर्तमान ब्राउज़र संगतता मोज़िला वेब डॉक्स के लिए जाँच करने में उनका समर्थन नहीं कर सकते हैं ।

flatMap()विधि क्या करती है पहले कॉलबैक फ़ंक्शन का उपयोग प्रत्येक तत्व को तर्क के रूप में करता है, फिर परिणाम को एक नए सरणी (2d सरणी अब 1d है क्योंकि तत्वों को चपटा हुआ है) में समतल करता है।

फ़ंक्शन का उपयोग कैसे करें, इसका एक उदाहरण यहां दिया गया है:

let arr = [[2], [4], [6], [8]]

let newArr = arr.flatMap(x => [x * 2]);

console.log(newArr);

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.