2016-09-26 18 views
3

joinが文字列には限定されていないのと同様に、複数の配列を連結する機能がありますか(区切り文字も配列です)?配列デリメータ(「散在」)で配列の結合を結合する

この関数は、標準JSまたはlodashのようなメジャーライブラリの一部である可能性があります(これがタグで参照される理由です)。ここで

は使い方の例です:

let numbers = [[1], [2], [3]]; 
let result = _.joinArrays(numbers, [0]); 
console.log(result); 
//printed: [1, 0, 2, 0, 3] 

これはに似ている:

let strings = ["a", "b", "c"]; 
let result = strings.join(","); 
console.log(result); 
//printed: "a,b,c"; 

それは私にはない文字列に値を回すしかし、joinを使用することはできません起こりたい

しかし、どのタイプでも動作します。

+1

さらにいくつかの例を追加してください。 –

+1

目的の機能名は、配列を別の要素で[intersperse](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-List.html#v:intersperse)することです。現在、Lodashのための[機能リクエスト](https://github.com/lodash/lodash/issues/2339)ですので、ライブラリに追加したいのであれば、アップアップしてください! – 4castle

+0

@ 4castle Oh cool。多分私はプルリクエストを提出するでしょう。ありがとうございました!! – GregRos

答えて

8

あなたは、単に配列をCONCAT、そして、あなたの区切り文字として使用したいいままでプッシュするarray.reduceを使用することができます。あなたはArray#reduceを使用し、必要に応じてアイテムや接着剤での配列を返すことができ

let numbers = [[1], [2], [3]]; 
 

 
let n = numbers.reduce((a, b) => a.concat(0, b)) 
 

 
console.log(n)

+0

もっと簡単に言うと、 'return a.concat(0、b)' – 4castle

+0

@ 4castle - 明らかに素晴らしいものです。どうも。 ; ) – DavidDomain

+0

これは悲しいことに、質問に答えません。それが私の最初の考えでした。 すべてのサブアレイにconcatを同時に適用する方が良いかもしれません( 'Array.prototype.concat.apply')。 – TylerY86

3

Matrix Interspersion

ここでフル・モンティです。怒る。

var numbers = [ 
 
    [1, 2, 3], 
 
    [4, 5, 6], 
 
    [7, 8, 9] 
 
], 
 
    delimiters = [ 
 
    ',', '-', 'x' 
 
]; 
 

 
// matrix interspersion, delimiters into numbers's children 
 
// the rank/order/whatevs of the matrix can be arbitrary and variable 
 
numbers.forEach((x, i) => { 
 
    for (var j = 1, l = x.length; j <= l; j+=2) 
 
    x.splice(j, 0, delimiters[i]); 
 
}) 
 

 
alert("Matrix interspersed: " + JSON.stringify(numbers)); 
 

 
// normal interspersion, a static delimiter into numbers 
 
for (var j = 1, l = numbers.length; j <= l; j+=2) 
 
    numbers.splice(j, 0, ' AND '); 
 

 
alert("Outer array interspersed: " + JSON.stringify(numbers)); 
 

 
// flattening a 2 rank array into a single array 
 
var flattened = Array.prototype.concat.apply([], numbers); 
 

 
alert("Flattened: " + JSON.stringify(flattened));

+0

joinを使うことはできません。 – GregRos

+0

ああ、結果を配列にしたいのですか?区切り文字を平らにして散在させるだけでいいですか?結合する配列の配列の実例と、散在する区切り文字の配列を教えてください。 – TylerY86

+0

ああ、私は参照してください。 Lodashを使ったもう一つの例は正しいです。 – TylerY86

0
var result = [].concat.apply([], numbers); 

console.log(result) 
0

。ここで

const join = (array, glue) => array.reduce((a, b) => a.concat(glue, b)); 
 

 
var numbers = [[1], [2], [3]]; 
 

 
console.log(join(numbers, [0])); 
 
console.log(join(numbers, [42, 43])); 
 
console.log(join([[1]], [0]));
.as-console-wrapper { max-height: 100% !important; top: 0; }

+2

reduce: 'array.reduce((r、a)=> r.concat(glue、a))'から3次ステートメントと初期値を削除することができます。 – 4castle

0

場合には他の誰かがそれをやりたい、いくつかの余分なロジックで、これを行う機能を実装したものです。私は本当にこれがすでに存在するかどうかについて本当に尋ねていた。

ロダッシュが必要です。

export function intersperse(arrs, delimeter) { 
    let joined = []; 
    for (var i = 0; i < arrs.length; i++) { 
     let arr = arrs[i]; 
     if (!arr) continue; //handle sparse arrays 
     joined.push(...arr); 
     if (i === arrs.length - 1) break; 
     if (_.isFunction(delimeter)) { 
      joined.push(...delimeter()); 
     } else if (_.isArray(delimeter)) { 
      joined.push(...delimeter); 
     } else { 
      throw new Error("unknown type"); 
     } 
    } 
    return joined; 
} 
0

4Castleのコメントを含む多くの良い答えがここにあります。変更については、この仕事のために一般Array.prototype.intersperse()を開発したいと思います。

機能的なJSでは、この仕事には3つの選択肢があります。

Array.prototype.intersperse_1 = function(s){ 
    return this.reduce((p,c,i) => (p[2*i]=c,p), new Array(2*this.length-1).fill(s)); 
}; 
Array.prototype.intersperse_2 = function(s){ 
    return this.reduce((p,c,i) => (i ? p.push(s,c) : p.push(c),p),[]); 
}; 
Array.prototype.intersperse_3 = function(s){ 
    return this.reduce((p,c,i) => i ? p.concat([s],[c]) : p.concat([c]),[]); 
}; 

.concat()が機能JSの中で最も高価な業務の一つであるので、あなたは離れて第三1から滞在する必要があります。 100Kアイテムでもジョブを完了することはできません。

一方、小型アレイでは常に少し速いですが、FFとChromeの両方の非常に大きなアレイでは、第1のものは第2のものよりも2倍以上高速です。すなわち、第1は1000M秒未満で10Mアイテムアレイを散在させ、第2は第2に2000~2500msecを要する。もちろんこのサイズを扱うことは、3回目では不可能です。

この特殊なケースでは、結果をプリミティブな値にマップする必要があるため、カスタマイズされたソリューションと比べておそらく高価になりますが、次のコードに注目する価値はあると思います。配列の長さがある特定の数字を超えている場合、.concat()のソリューションを採用することがこれより遅くなると確信しています。

Array.prototype.intersperse = function(s){ 
 
    return this.reduce((p,c,i) => (p[2*i]=c,p), new Array(2*this.length-1).fill(s)); 
 
} 
 

 
var arr = [[1],[2],[3]], 
 
result = arr.intersperse([0]) 
 
      .map(e => e[0]); 
 
console.log(JSON.stringify(result));

+0

別のアイデア: 'Array.from({length:2 * this.length-1}、(v、i)=> i&1?s:this [i >>> 1]) ';私はそれがあなたの第2版をゆっくりとさせるメモリのサイズの増加とそれによる再割り当てを繰り返すと思います。 – Thomas

+0

@トーマス興味深いアプローチですが、1M +アイテム配列でテストした場合、FFとクロームの両方で常にベストを尽くしているようです。 [this](https://repl.it/Dh7N)の10Mアイテムのパフォーマンステストを確認してください。あなたがそれを変更できるかもしれない。 – Redu

0

としてはすでにここ数回を述べ、これを実行する最も簡単な方法は、

function intercalate(glue, arr){ 
    return arr.reduce((acc, v) => acc.concat(glue, v)); 
} 

ですが、それはすべての繰り返しAで作成されますので、これは、最善の方法ではありません新しい(中間の)配列は、次に破棄されます。この短い値の配列ではこれは重要ではありませんが、もっと長い配列でこれを使うつもりならば、その影響に気付くかもしれません。

ベター

function intercalate(glue, arr){ 
    const push = (acc, v) => (Array.isArray(v)? acc.push(...v): acc.push(v), acc); 
    return arr.reduce((acc, v, i) => push(i===0? acc: push(acc, glue), v), []); 
} 

。彼らが来るよう、1つのアレイを作成し、そのに値をプッシュするだろう。しかし、この配列が徐々に増加しているので、それはまだ大きなメモリの塊とコピーを割り当てる必要があるかもしれませんデータ。これらのタスクは非常にパフォーマンスが良いが、依然として不要です(imo)。私たちはより良くすることができます。

まず、すべての配列と区切り文字を含むリストを作成し、concat.apply([], list)を使用してこれを平坦化します。したがって、私たちは事前に計算できるサイズの1つの中間配列を生成し、残りはArray.concatの問題であり、基本実装です。それが渡された値に依存してもよいし、天気をかJITコンパイラがSを最適化するので

function intersperse(delimiter, arr){ 
    if(!arr.length) return []; 
    let j = 0, push = (acc, v) => (acc[j++] = v, acc); 
    return arr.reduce((acc, v) => push(j===0? acc: push(delimiter, glue), v), Array(2*arr.length-1)); 
} 
//or 
function intersperse(delimiter, arr){ 
    if(!arr.length) return []; 
    var out = Array(2*arr.length-1); 
     out[0] = arr[0]; 
    for(var i=1, j=1; j<out.length;){ 
     out[j++] = delimiter; 
     out[j++] = arr[i++]; 
    } 
    return out; 
} 

//and 

function intercalate(glue, arr){ 
    var emptyArray = []; 
    return arr.length? 
     emptyArray.concat.apply(emptyArray, intersperse(glue, arr)): 
     emptyArray; 
} 

WICHのバージョンが最速/最高となり、最終的には、言うことそれは容易ではありません***アウトそれの。私はポイントを作った、それはあなたが使用するバージョン/実装を選択するのはあなた次第です。

最初のバージョンに:あなたは全くのlibにこれを入れないことを好むが、ほとんどインラインをそれを書くことが(それは短く、そのために十分に簡単です)、したがって、JITコンパイラは、いくつかを見つけるためにしようとしないかもしれません異なるコールの共通タイプ(#monomorphic function/code)となり、したがって、それぞれの発生を別々に最適化します。一方、これは時期尚早の最適化である可能性があります。それはあなた次第です。

関連する問題