.map () एक जावास्क्रिप्ट ES6 मानचित्र?


98

आप यह कैसे करेंगे? सहज रूप से, मैं करना चाहता हूं:

var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]);

// wishful, ignorant thinking
var newMap = myMap.map((key, value) => value + 1); // Map { 'thing1' => 2, 'thing2' => 3, 'thing3' => 4 }

मैंने नए पुनरावृत्ति प्रोटोकॉल पर प्रलेखन से बहुत अधिक चमक नहीं ली है

मैं के बारे में पता कर रहा हूँ wu.js , लेकिन मैं एक चल रहा हूँ कोलाहल परियोजना और नहीं शामिल करना चाहते हैं Traceur है, जो ऐसा लगता है जैसे कि यह वर्तमान पर निर्भर करता है

मैं थोड़ा क्लूलेस भी हूं कि कैसे फिटज़ेन / wu.js को निकालने के लिए इसे मैंने अपने प्रोजेक्ट में किया।

मैं यहाँ क्या याद कर रहा हूँ की एक स्पष्ट, संक्षिप्त विवरण प्यार करता हूँ। धन्यवाद!


ES6 मानचित्र , FYI के लिए डॉक्स


क्या आप उपयोग करने में सक्षम हैं Array.from?
Ry-

@minitech संभवतः, एक साथ polyfill ... वहाँ नहीं इसके बिना यह करने के लिए एक तरीका है?
नीज़ेर

खैर, आप mapiterables पर उपयोग के लिए अपने स्वयं के फ़ंक्शन लिख सकते हैं , का उपयोग कर for of
Ry-

सुपर नाइटपिक, लेकिन अगर आप वास्तव में एक मैप पर मैप करने जा रहे थे, तो आपको अंत में एक मैप वापस मिलेगा। अन्यथा आप पहले एक मानचित्र को एक सरणी में परिवर्तित कर रहे हैं और एक सरणी पर मैपिंग कर रहे हैं, न कि .map () एक मैप को आईएनजी। आप आसानी से एक आईएसओ का उपयोग करके मानचित्र पर मैप कर सकते हैं: dimap (x => [... x], x => नया मानचित्र (x));
२०:४२

@ ठीक है, हम शायद अपनी खुद की प्रोग्रामिंग भाषा लिख ​​सकते हैं, लेकिन क्यों ..? यह काफी सरल बात है और अधिकांश प्रोग्रामिंग भाषाओं में कई दशकों से मौजूद है।
रूबल

जवाबों:


79

तो .mapखुद को केवल एक मूल्य प्रदान करता है जिसकी आपको परवाह है ... उस ने कहा, इससे निपटने के कुछ तरीके हैं:

// instantiation
const myMap = new Map([
  [ "A", 1 ],
  [ "B", 2 ]
]);

// what's built into Map for you
myMap.forEach( (val, key) => console.log(key, val) ); // "A 1", "B 2"

// what Array can do for you
Array.from( myMap ).map(([key, value]) => ({ key, value })); // [{key:"A", value: 1}, ... ]

// less awesome iteration
let entries = myMap.entries( );
for (let entry of entries) {
  console.log(entry);
}

ध्यान दें, मैं उस दूसरे उदाहरण में बहुत सारे नए सामान का उपयोग कर रहा हूं ... ... Array.fromकोई भी पुनरावृत्ति लेता है (किसी भी समय आप उपयोग करेंगे [].slice.call( ), प्लस सेट और मैप्स) और इसे एक सरणी में बदल देता है ... ... मैप्स , जब एक सरणी में coerced, सरणियों की एक सरणी में बदल जाते हैं, जहां el[0] === key && el[1] === value;(मूल रूप से, एक ही प्रारूप में कि मैं अपने उदाहरण के साथ मैप किया था, ऊपर)।

मैं लैंबडा की तर्क स्थिति में सरणी के विनाश का उपयोग कर रहा हूं, प्रत्येक ए एल के लिए एक ऑब्जेक्ट वापस करने से पहले उन एरे स्पॉट को मूल्यों पर नियत करने के लिए।

यदि आप उत्पादन में बैबेल का उपयोग कर रहे हैं, तो आपको बैबेल के ब्राउज़र पॉलीफिल (जिसमें "कोर-जेएस" और फेसबुक के "रीजनरेटर" शामिल हैं) का उपयोग करने की आवश्यकता है।
मैं इसमें शामिल हूं Array.from


हाँ, बस यह देखते हुए कि ऐसा लगता है कि मुझे ऐसा करने की आवश्यकता होगी Array.from। आपका पहला उदाहरण किसी सरणी, btw को वापस नहीं करता है।
नीज़ेर

@ नीजर नहीं, यह नहीं है। हर समय फ्लैट .forEachरिटर्न undefined, जैसा कि अपेक्षित उपयोग forEachएक साधारण साइड-इफेक्ट आधारित पुनरावृत्ति है (जैसा कि ईएस 5 के बाद से किया गया है)। इसका उपयोग करने के लिए forEach, आप एक सरणी का निर्माण करना चाहते हैं और इसे हाथ से forEachया तो कह सकते हैं , या तो कहा जा सकता है .entries()या .keys( )या इसके द्वारा लौटाए गए पुनरावृत्त के माध्यम से .values( )Array.fromकुछ भी करने का मन नहीं कर रहा है, यह अनोखा है, यह सिर्फ उस विशेष कुरूपता को छिपाता है, जो कहा जाता है। और हाँ, जाँच लें कि babel-core/browser.js(या जो कुछ भी है) आपको मिल जाएगा .from...
नॉरगार्ड

4
मेरा उत्तर देखें, Array.fromएक मानचित्र फ़ंक्शन को एक परम के रूप में लेता है, आपको इसे खत्म करने और इसे त्यागने के लिए एक अस्थायी सरणी बनाने की आवश्यकता नहीं है।
loganfsmyth

क्या आप बता सकते हैं कि वस्तु को उसके चारों ओर लिपटे हुए कोष्ठक की आवश्यकता क्यों है? मैं अभी भी ES6 के लिए थोड़ा नया हूँ और उस हिस्से को समझने में परेशानी हो रही है। developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… का कहना है कि यह एक लेबल के रूप में व्याख्या करता है और यह निश्चित नहीं है कि इसका क्या अर्थ है
dtc

1
@dtc हाँ, जब आप एक ऑब्जेक्ट लिखते हैं तो आप लिखते हैं const obj = { x: 1 };, जब आप कोड का एक ब्लॉक लिखते हैं if (...) { /* block */ }, तो आप लिखते हैं , जब आप लिखते हैं एक एरो फ़ंक्शन लिखते हैं () => { return 1; }, तो यह कैसे पता चलता है जब यह एक फ़ंक्शन बॉडी, बनाम किसी ऑब्जेक्ट का ब्रेसिज़ है? और इसका उत्तर है कोष्ठक। अन्यथा, यह उम्मीद करता है कि नाम एक कोड-ब्लॉक के लिए एक लेबल है जो शायद ही कभी इस्तेमाल की जाने वाली सुविधा है, लेकिन आप एक switchया एक लूप को लेबल कर सकते हैं , ताकि आप break;उन्हें नाम से बाहर कर सकें । इसलिए यदि यह गायब है, तो आपके पास एक फ़ंक्शन बॉडी है, जिसमें एक लेबल और स्टेटमेंट है 1,
एमडीएन

35

आपको बस स्प्रेड ऑपरेटर का उपयोग करना चाहिए :

var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]);

var newArr = [...myMap].map(value => value[1] + 1);
console.log(newArr); //[2, 3, 4]

var newArr2 = [for(value of myMap) value = value[1] + 1];
console.log(newArr2); //[2, 3, 4]


ऐसा लगता है कि अभी भी इसकी आवश्यकता है Array.from, FYI करें।
नीज़ेर

1
@neezer आपको पूरी तरह से, सकारात्मक रूप से अपने पृष्ठ पर, उत्पादन में बेबल-ट्रांसकोड किए गए कोड का उपयोग करने के लिए, बैबेल की पॉलीफ़िल का उपयोग करना चाहिए । इसके आसपास कोई रास्ता नहीं है, जब तक कि आप उन सभी तरीकों (फेसबुक के
रीजनरेटर

@Norguard मिला - बस एक विन्यास परिवर्तन जो मुझे करने की आवश्यकता है, वह सब मेरा मतलब है। एक तरफ, वास्तव में। :)
नीपर

5
बस ध्यान दें, [...myMap].map(mapFn)एक अस्थायी सरणी बनाने जा रहा है और फिर इसे छोड़ दें। Array.fromएक लेता है mapFnअपनी दूसरी तर्क के रूप में, बस का उपयोग करें कि।
लोगानफैशिथ

2
@wZVanG क्यों नहीं Array.from(myMap.values(), val => val + 1);?
लोगनफ़्समीथ

22

बस उपयोग करें Array.from(iterable, [mapFn])

var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]);

var newArr = Array.from(myMap.values(), value => value + 1);

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

यह बहुत अच्छा है। और यह Map.values()Array.values ​​() जो अभी भी नहीं करता है के विपरीत, का उपयोग करते हुए , फ्लो के साथ अच्छा खेलता है :
चेहरा

4

आप इस फ़ंक्शन का उपयोग कर सकते हैं:

function mapMap(map, fn) {
  return new Map(Array.from(map, ([key, value]) => [key, fn(value, key, map)]));
}

उपयोग:

var map1 = new Map([["A", 2], ["B", 3], ["C", 4]]);

var map2 = mapMap(map1, v => v * v);

console.log(map1, map2);
/*
Map { A → 2, B → 3, C → 4 }
Map { A → 4, B → 9, C → 16 }
*/

3

का उपयोग करते हुए Array.fromमैंने लिखा एक टाइपप्रति समारोह है कि मूल्यों के नक्शे:

function mapKeys<T, V, U>(m: Map<T, V>, fn: (this: void, v: V) => U): Map<T, U> {
  function transformPair([k, v]: [T, V]): [T, U] {
    return [k, fn(v)]
  }
  return new Map(Array.from(m.entries(), transformPair));
}

const m = new Map([[1, 2], [3, 4]]);
console.log(mapKeys(m, i => i + 1));
// Map { 1 => 3, 3 => 5 }

3

वास्तव में आप अभी भी Mapसरणी के साथ परिवर्तित करने के बाद मूल कुंजी के साथ कर सकते हैं Array.from। यह एक ऐरे को वापस करके संभव है , जहां पहला आइटम है key, और दूसरा ट्रांसफ़ॉर्म किया गया है value

const originalMap = new Map([
  ["thing1", 1], ["thing2", 2], ["thing3", 3]
]);

const arrayMap = Array.from(originalMap, ([key, value]) => {
    return [key, value + 1]; // return an array
});

const alteredMap = new Map(arrayMap);

console.log(originalMap); // Map { 'thing1' => 1, 'thing2' => 2, 'thing3' => 3 }
console.log(alteredMap);  // Map { 'thing1' => 2, 'thing2' => 3, 'thing3' => 4 }

यदि आप पहले सरणी आइटम के रूप में उस कुंजी को वापस नहीं करते हैं , तो आप अपनी Mapचाबियाँ ढीली करते हैं ।


1

मैं मानचित्र का विस्तार करना पसंद करता हूं

export class UtilMap extends Map {  
  constructor(...args) { super(args); }  
  public map(supplier) {
      const mapped = new UtilMap();
      this.forEach(((value, key) => mapped.set(key, supplier(value, key)) ));
      return mapped;
  };
}

1

आप मूल्य बदलने के लिए map.set का उपयोग करके myMap.forEach और प्रत्येक लूप में उपयोग कर सकते हैं।

myMap = new Map([
  ["a", 1],
  ["b", 2],
  ["c", 3]
]);

for (var [key, value] of myMap.entries()) {
  console.log(key + ' = ' + value);
}


myMap.forEach((value, key, map) => {
  map.set(key, value+1)
})

for (var [key, value] of myMap.entries()) {
  console.log(key + ' = ' + value);
}


मुझे लगता है कि यह बात याद आती है। Array.map कुछ भी म्यूट नहीं करता है।
आरोन


0

यदि आप संपूर्ण मानचित्र को पहले से किसी सरणी में बदलना नहीं चाहते हैं, और / या विनाश कुंजी-मूल्य सरणियों में, आप इस मूर्खतापूर्ण फ़ंक्शन का उपयोग कर सकते हैं:

/**
 * Map over an ES6 Map.
 *
 * @param {Map} map
 * @param {Function} cb Callback. Receives two arguments: key, value.
 * @returns {Array}
 */
function mapMap(map, cb) {
  let out = new Array(map.size);
  let i = 0;
  map.forEach((val, key) => {
    out[i++] = cb(key, val);
  });
  return out;
}

let map = new Map([
  ["a", 1],
  ["b", 2],
  ["c", 3]
]);

console.log(
  mapMap(map, (k, v) => `${k}-${v}`).join(', ')
); // a-1, b-2, c-3


0
Map.prototype.map = function(callback) {
  const output = new Map()
  this.forEach((element, key)=>{
    output.set(key, callback(element, key))
  })
  return output
}

const myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]])
// no longer wishful thinking
const newMap = myMap.map((value, key) => value + 1)
console.info(myMap, newMap)

संपादन प्रोटोटाइप से बचने में अपने धार्मिक उत्साह पर निर्भर करता है, लेकिन, मुझे लगता है कि यह मुझे सहज रखने देता है।


0

आप मैप () एरेज़ कर सकते हैं, लेकिन मैप्स के लिए ऐसा कोई ऑपरेशन नहीं है। डॉ। एक्सल रस्शमेयर से समाधान :

  • नक्शे को [कुंजी, मान] जोड़े की एक सरणी में बदलें।
  • सरणी को मैप या फ़िल्टर करें।
  • परिणाम को मानचित्र में वापस कनवर्ट करें।

उदाहरण:

let map0 = new Map([
  [1, "a"],
  [2, "b"],
  [3, "c"]
]);

const map1 = new Map(
  [...map0]
  .map(([k, v]) => [k * 2, '_' + v])
);

परिणामस्वरूप

{2 => '_a', 4 => '_b', 6 => '_c'}

-1

शायद इस तरह:

const m = new Map([["a", 1], ["b", 2], ["c", 3]]);
m.map((k, v) => [k, v * 2]); // Map { 'a' => 2, 'b' => 4, 'c' => 6 }

आपको पहले केवल बन्दर पैच की आवश्यकता होगी Map:

Map.prototype.map = function(func){
    return new Map(Array.from(this, ([k, v]) => func(k, v)));
}

हम इस पैच का एक सरल रूप लिख सकते हैं:

Map.prototype.map = function(func){
    return new Map(Array.from(this, func));
}

लेकिन हम हमें उस समय लिखने के लिए मजबूर कर देते थे m.map(([k, v]) => [k, v * 2]);जो मुझे थोड़ा अधिक दर्दनाक और बदसूरत लगता है।

केवल मैपिंग मान

हम केवल मूल्यों को मैप कर सकते हैं, लेकिन मैं उस समाधान के लिए जाने की सलाह नहीं दूंगा क्योंकि यह बहुत विशिष्ट है। फिर भी यह किया जा सकता है और हमारे पास निम्नलिखित एपीआई होंगे:

const m = new Map([["a", 1], ["b", 2], ["c", 3]]);
m.map(v => v * 2); // Map { 'a' => 2, 'b' => 4, 'c' => 6 }

इस तरह पैच करने से पहले:

Map.prototype.map = function(func){
    return new Map(Array.from(this, ([k, v]) => [k, func(v)]));
}

हो सकता है कि आपके पास दोनों हों, दूसरे mapValuesका नामकरण यह स्पष्ट करने के लिए कि आप वास्तव में ऑब्जेक्ट की मैपिंग नहीं कर रहे हैं क्योंकि यह संभवतः अपेक्षित होगा।

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