.map()Javascript ES6マップ?


97

これをどのように行いますか?本能的に、私はしたい:

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それは現在に依存のようにそれはそうと

また、fitzgen /wu.jsがどのようにそれを自分のプロジェクトに取り入れたかを抽出する方法についても少しわかりません

私がここで欠けているものの明確で簡潔な説明が欲しいです。ありがとう!


ES6マップのドキュメント、FYI


使えArray.fromますか?
–ry-

@minitechおそらく、ポリフィルを使用すると...それなしでこれを行う方法はありませんか?
neezer 2015年

mapを使用して、iterableで使用する独自の関数を作成できますfor of
–ry-

非常に簡単ですが、実際にマップ上にマップする場合は、最後にマップが返されます。それ以外の場合は、最初にマップを配列に変換し、マップを.map()するのではなく、配列にマッピングするだけです。ISOを使用すると、マップ上に簡単にマップできます。dimap(x => [... x]、x => new Map(x));
dtipson 2016

@Ryええと、私たちはおそらく独自のプログラミング言語を書くことができますが、なぜ..?これは非常に単純なことであり、ほとんどのプログラミング言語に何十年も存在します。
ruX 2018年

回答:


79

したがって、.mapそれ自体はあなたが気にかけている1つの価値しか提供しません...とはいえ、これに取り組むにはいくつかの方法があります。

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

注:この2番目の例では、多くの新しいものを使用しています... ...Array.from反復可能なもの(使用するときはいつでも[].slice.call( )、さらにセットとマップ)を取り、それを配列に変換します......マップ、配列に強制変換されると、配列の配列に変わります。ここでel[0] === key && el[1] === value;(基本的に、上記の例のマップに事前に入力したのと同じ形式で)。

各elのオブジェクトを返す前に、ラムダの引数位置にある配列の非構造化を使用して、それらの配列スポットを値に割り当てています。

本番環境でBabelを使用している場合は、Babelのブラウザポリフィル(「core-js」とFacebookの「regenerator」を含む)を使用する必要があります。
私はそれが含まれていると確信していますArray.from


ええ、Array.fromこれを行うには必要なように見えることに気づきました。最初の例では、配列は返されません。
neezer 2015年

@neezerいいえ、そうではありません。予想される使用法は単純な副作用ベースの反復であるため(ES5以降と同じ)、常にフラットに.forEach戻ります。これを使用するには、配列を作成し、前述の方法、またはまたはによって返されるイテレータを介して、手動で配列を作成します。驚くほどユニークなことは何もしていません。それは、前述のトラバーサルを行うことの特定の醜さを隠しているだけです。そして、はい、あなたが得るもの(またはそれが何であれ)を含めることによってそれをチェックしてください...undefinedforEachforEachforEach.entries().keys( ).values( )Array.frombabel-core/browser.js.from
Norguard 2015年

4
私の答えを参照してくださいArray.from。map関数をparamとして受け取ります。一時的な配列を作成して、その上にマップして破棄するだけで済みます。
loganfsmyth 2015年

オブジェクトを括弧で囲む必要がある理由を説明できますか?私はまだES6に少し慣れておらず、その部分を理解するのに苦労しています。developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…は、ラベルとして解釈され、それが何を意味するのかわからないと言っています
dtc 2017年

1
@dtcええ、あなたが書くオブジェクトを書くconst obj = { x: 1 };とき、あなたがコードのブロックを書くif (...) { /* block */ }とき、あなたが書くとき、あなたが書く矢印関数を書くとき() => { return 1; }、それでそれが関数本体であるか、オブジェクトの中括弧であるかをどうやって知るのですか?そして答えは括弧です。それ以外の場合、名前はめったに使用されない機能のコードブロックのラベルであると想定されますが、switchまたはループにラベルbreak;を付けて、名前でそれらから外すことができます。したがって、欠落している場合は1、MDNの例に基づいたラベル付きの関数本体とステートメントがあります
Norguard

35

Spread演算子を使用する必要があります:

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、参考までに。
neezer 2015年

1
@neezerは、本番環境でページでBabelトランスパイルコードを使用するために、絶対に積極的にBabelのポリフィルを使用する必要があります。これらすべてのメソッド(FacebookのRegeneratorを含む)を自分で手動で実装しない限り、それを回避する方法はありません...
Norguard 2015年

@Norguard了解しました。構成を変更するだけで十分です。余談ですが、本当に。:)
neezer 2015年

5
念のために[...myMap].map(mapFn)言っておきますが、一時配列を作成してから破棄します。2番目の引数としてをArray.from取りますmapFn。それを使用してください。
loganfsmyth 2015年

2
@wZVanGどうしてArray.from(myMap.values(), val => val + 1);
loganfsmyth 2015年

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()、オプションの2番目のパラメーターとしてマッピング関数を使用していることに気づいていません。
Andru

これはとてもいいです。そして、それはあまりにも流れに素敵を果たしている、使用している場合Map.values()とは異なり、Array.values()はまだない:手のひらを顔に当てる:
ericsocoを

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、値をマップする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 }

3

実際には、Mapを使用して配列に変換した後でも、元のキーを使用できますArray.from。これは、最初の項目が、で、2番目の項目が変換された配列である配列を返すことで可能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

myMap.forEachを使用でき、各ループでmap.setを使用して値を変更できます。

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

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

マップ全体を事前に配列に変換したり、Key-Value配列を分解したりしたくない場合は、次のばかげた関数を使用できます。

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

map()配列を使用できますが、Mapsにはそのような操作はありません。アクセルラウシュマイヤー博士からの解決策:

  • マップを[key、value]ペアの配列に変換します。
  • 配列をマップまたはフィルタリングします。
  • 結果をマップに変換し直します。

例:

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]);もう少し苦痛で醜いようです。

マッピング値のみ

値のみをマップすることもできますが、具体的すぎるため、そのソリューションを選択することはお勧めしません。それでもそれは可能であり、次のAPIがあります。

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

おそらく両方を持つことができ、2番目の名前を付けて、mapValuesおそらく予想されるように実際にオブジェクトをマッピングしていないことを明確にします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.