.карте() в JavaScript ES6 в карте?


Как бы вы это сделали? Инстинктивно я хочу сделать:

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 }

Я мало что почерпнул из документация по новому протоколу итерации.

Я в курсе Ву.js, а я Бабель проект и не хочу включать Трейсер, который похоже, что в настоящее время это зависит от.

Я также немного не знаю, как извлечь как fitzgen / wu.на JS сделал это в мой собственный проект.

хотел бы четкое, краткое объяснение того, что я здесь упускаю. Спасибо!


документы для ES6 Map, FYI

8 54

8 ответов:

так .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 принимает любой iterable (в любое время вы будете использовать [].slice.call( ) плюс наборы и карты) и превращает его в массив... ...Карты, когда их принудительно помещают в массив, превращаются в массив массивов, где el[0] === key && el[1] === value; (в основном, в том же формате, что я предварительно заполнил мой пример карты, выше).

Я используя деструктуризацию массива в позиции аргумента лямбды, чтобы назначить эти пятна массива значениям, прежде чем возвращать объект для каждого el.

если вы используете Babel, в производстве вам нужно будет использовать браузер Babel polyfill (который включает в себя "core-js" и "регенератор"Facebook).
Я совершенно уверен, что он содержит Array.from.

вы должны просто использовать распространение оператор:

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(iterable, [mapFn]).

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

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

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 }

используя Array.from Я написал функцию Typescript, которая отображает значения:

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 }

Если вы не хотите заранее конвертировать всю карту в массив и / или разрушать массивы ключей-значений, вы можете использовать эту глупую функцию:

/**
 * 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
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)

зависит от вашего религиозного рвения в избегании редактирования прототипов, но, я считаю, что это позволяет мне держать его интуитивно понятным.

Я предпочитаю расширять карту

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;
  };
}