.map() a Javascript ES6 Map?

前端 未结 13 2136
不思量自难忘°
不思量自难忘° 2020-12-04 20:53

How would you do this? Instinctively, I want to do:

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

// wishful, ignorant thinking
         


        
相关标签:
13条回答
  • 2020-12-04 21:12
    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)
    

    Depends on your religious fervor in avoiding editing prototypes, but, I find this lets me keep it intuitive.

    0 讨论(0)
  • 2020-12-04 21:14

    const mapMap = (callback, map) => new Map(Array.from(map).map(callback))
    
    var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]);
    
    var newMap = mapMap((pair) => [pair[0], pair[1] + 1], myMap); // Map { 'thing1' => 2, 'thing2' => 3, 'thing3' => 4 }

    0 讨论(0)
  • 2020-12-04 21:19

    If you don't want to convert the entire Map into an array beforehand, and/or destructure key-value arrays, you can use this silly function:

    /**
     * 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 讨论(0)
  • 2020-12-04 21:22

    You should just use Spread operator:

    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]

    0 讨论(0)
  • 2020-12-04 21:23

    Using Array.from I wrote a Typescript function that maps the values:

    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 }
    
    0 讨论(0)
  • 2020-12-04 21:24

    Maybe this way:

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

    You would only need to monkey patch Map before:

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

    We could have wrote a simpler form of this patch:

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

    But we would have forced us to then write m.map(([k, v]) => [k, v * 2]); which seems a bit more painful and ugly to me.

    Mapping values only

    We could also map values only, but I wouldn't advice going for that solution as it is too specific. Nevertheless it can be done and we would have the following API:

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

    Just like before patching this way:

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

    Maybe you can have both, naming the second mapValues to make it clear that you are not actually mapping the object as it would probably be expected.

    0 讨论(0)
提交回复
热议问题