2015-06-27 5 views
45

Как вы это сделаете? Инстинктивно, я хочу сделать:.map() Карта 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 } 

Я не подбирала много от documentation on the new iteration protocol.

Я знаю wu.js, но я бег Babel проекта и не хочу включать Traceur, который it seems like it currently depends on.

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

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


Docs for ES6 Map, FYI

+0

возможность использовать 'Array.from' ли вы? – Ryan

+0

@minitech Возможно, с [polyfill] (http://babeljs.io/docs/advanced/caveats/) ... нет ли способа сделать это без него? – neezer

+0

Ну, вы можете написать свою собственную функцию 'map' для использования в iterables, используя' for for'. – Ryan

ответ

35

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

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

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

+0

Да, просто заметив, что мне кажется, что мне понадобится «Array.from», чтобы это сделать. Ваш первый пример не возвращает массив, кстати. – neezer

+0

@neezer нет, это не так. '.forEach' возвращает' undefined', все время, так как ожидаемое использование 'forEach' - простая итерация на основе побочных эффектов (такая же, как и с ES5). Чтобы использовать этот 'forEach', вы хотите построить массив и заполнить его вручную либо через указанный' forEach', либо через итератор, возвращаемый '.entries()' или '.keys()' или ' .values ​​() '. 'Array.from' не делает ничего уникального для ума, он просто скрывает это особое уродство в выполнении этого обхода. И да, убедитесь, что, включив 'babel-core/browser.js' (или что-то еще), вы получаете' .from' ... – Norguard

+1

См. Мой ответ: 'Array.from' берет функцию карты как параметр, вы не нужно создавать временный массив, чтобы отображать его и отбрасывать. – loganfsmyth

16

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

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]

+1

... святое дерьмо, почему я не помню, что распространение работает на всех итерациях ... – Norguard

+0

Выглядит как это все еще требует 'Array.from', FYI. – neezer

+1

@neezer вы абсолютно, положительно * должны * использовать полиполки Вавилона, чтобы использовать код Babel-transpiled на вашей странице, на производстве. Нет никакого способа обойти это, если вы не реализуете все эти методы (включая Регенератор Facebook) самостоятельно, вручную ... – Norguard

11

Array.from(iterable, [mapFn]) Просто используйте.

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

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

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

Использование 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 } 
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

Смежные вопросы