2016-05-11 8 views
4

ES6のSetを使用して一部の文字列から一意の文字を取得したいと考えています。 それでは、私たちは、文字列var str = 'abcdeaabc';を持っており、この文字列から文字のセット作成することを想定してみましょう:abcdSetオブジェクトでArray.prototype.mapを呼び出せない理由

var str = 'abcdeaadbc'; 
var chars = new Set(str); 

は、今、私たちは、ユニークな文字のセットを持っています。 私はcharセットがforEachメソッドを持っており、何のmap方法を持っていないことに驚きました。

セットが反復可能なオブジェクトであるので、なぜ我々はセットを反復するmap機能を使用することはできませんか?

私はArray.prototype.mapにこの方法をcharsセットとchars.values() SetIteratorを渡そうとしました:

Array.prototype.map.call(chars, function(element) {...}); 
Array.prototype.map.call(chars.values(), function(element) {...}); 

しかし、すべてが失敗してみてください。

例えば、我々は文字列からユニークなシンボルを取得し、アンダースコアの前でそれらの配列を返すようにしたいと仮定しましょう。例えば:ここで

['_a', '_b', '_c', '_d']は私の2つのソリューションです:

// First: 
var result = Array.from(chars).map(function(c) { 
    return '_' + c; 
}); 

// Second: 
var result = []; 
chars.forEach(function(c) { 
    this.push('_' + c); 
}, result); 

しかしSet文脈でArray.prototypeをのmap機能を呼び出す方法はありますか?もしそうでなければ - なぜ?

+0

'Set.entries'を試しましたか?実際には、2番目の考えでは、私はそれが動作するとは思わない... –

+0

はい、それはあまりにも失敗しました。 –

+2

http://stackoverflow.com/a/35374005/5812121また、代わりに、 '' let result = [... chars] .map(c => \ '_ $ {c} \'); ' – timolawl

答えて

4

Array.prototype.mapは、整数インデックスとlengthプロパティを持つ配列のような型で機能します。 SetMapは一般的なiterable型ですが、配列のようなものではないので、Array.prototypeメソッドは動作しません。例えば

var s = new Set([1, 2, 3]); 
s.length === undefined; 
s[0] === undefined 

主なアプローチは、あなたのソリューションのようなのArray.from種類がありますが、注意すべき一つのことは、あなたがいいと短いため

let results = Array.from(chars, c => `_${c}`); 

を行うことができますので、Array.fromは、第二引数としてmapFnかかることですマップは、イテラブルを配列に変換します。

+0

の設定エントリはインデックスからアクセスできませんが、順序は保証されています...私はこれを乗り越えることができません:) – maioman

+0

MDNは、 'Set'は反復可能です。そして、Array.prototype.mapの仕様は、マップがiterableオブジェクトを取得するということです:[MDN:map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)。だからなぜ私は 'map'の引数として渡すことができませんか? –

+0

@YuriyYakym Setインスタンスは配列canのような数値インデックスでは索引付けすることができず、配列は '.map()'、 '.filter()'、 '.forEach()'などのように機能するからですに頼る。 – Pointy

1

場合でもmapは、任意の配列のようなオブジェクトのために働くのに十分な汎用的であるため、必ずしもすべての反復可能なオブジェクトは配列に似ています。

mapは、lengthプロパティを取得した後、プロパティを0からlength-1に反復します。それはlengthの代わりにsizeがあり、その要素へのランダムアクセスを提供しないため、セットでは機能しません。

実際にmapを使用する場合は、セットを配列に変換してから、結果をセットに変換し直す必要があります。

var newSet = new Set(Array.from(set).map(myFunc)); 

しかし、唯一のセット操作を使用する方が良いだろう、ということにはポイントがありません:

var newSet = new Set(); 
for(let val of set) newSet.add(myFunc(val)); 

それとも自己呼び出された発電機の機能:

var newSet = new Set(function*() { 
    for(let val of set) yield myFunc(val); 
}()); 
+0

'Array.from'の結果をマッピングすることは、何らの理由もなく一時配列を作成します。コールバックを2番目のパラメータとして渡します。 – loganfsmyth

1

がいる場合あなたはこのようにすることが必死です。

var str = 'abcdeaadbc'; 
 
var chars = new Set(str); 
 
document.write("<pre>" + JSON.stringify([...chars].map(c => c+"up")) + "</pre>")

+0

拡散してからマッピングすると、何の理由もなく一時的な配列が作成されます。 Array.fromを使って配列とマップを同時に作ることができます。 – loganfsmyth

+1

@loganfsmyth:Array.from()メソッドは、配列のようなオブジェクトまたは反復可能なオブジェクトから新しいArrayインスタンスを作成します。 (これはMDNの 'Array.from()'の説明の最初の行です)https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from関数のプログラミングのように配列メソッドを関数のように使用するか、関数に固有の要素を引数配列として渡したいとします。そのために無駄な配列を作成する必要はありません。 – Redu

+0

私のポイントは '[... chars] .map(fn)'と 'Array.from(chars).map(fn)'の両方で配列を作成し、次に '.map'を呼び出して2番目の配列を返します。 'Array.from(chars、fn)'を実行して、最初の一時配列を作成しないようにすることができます。 – loganfsmyth

関連する問題