279

Python の zip 関数に相当する JavaScript はありますか? つまり、同じ長さの配列が複数あると、ペアの配列が作成されます。

たとえば、次のような 3 つの配列があるとします。

var array1 = [1, 2, 3];
var array2 = ['a','b','c'];
var array3 = [4, 5, 6];

出力配列は次のようになります。

var output array:[[1,'a',4], [2,'b',5], [3,'c',6]]
4

23 に答える 23

220

2016 更新:

これは、より洗練された Ecmascript 6 バージョンです。

zip= rows=>rows[0].map((_,c)=>rows.map(row=>row[c]))

イラスト相当。Python { }へzip(*args):

> zip([['row0col0', 'row0col1', 'row0col2'],
       ['row1col0', 'row1col1', 'row1col2']]);
[["row0col0","row1col0"],
 ["row0col1","row1col1"],
 ["row0col2","row1col2"]]

(そして FizzyTea は、ES6 には可変引数構文があることを指摘しているため、次の関数定義は python のように動作しますが、免責事項については以下を参照してください...これは独自の逆数ではないため、zip(zip(x))等しくはなりませんx; ただし、Matt Kramer が指摘するzip(...zip(...x))==xように (通常のpythonでzip(*zip(*x))==x))

代替定義の同等物。Python { }へzip:

> zip = (...rows) => [...rows[0]].map((_,c) => rows.map(row => row[c]))
> zip( ['row0col0', 'row0col1', 'row0col2'] ,
       ['row1col0', 'row1col1', 'row1col2'] );
             // note zip(row0,row1), not zip(matrix)
same answer as above

...現時点で、そしておそらく将来的に構文にパフォーマンスの問題が発生する可能性があることに注意してください。そのため、可変引数で2番目の回答を使用する場合は、パフォーマンステストを行うことをお勧めします。標準。)

これを文字列で使用する場合は、必ず補遺に注意してください (おそらく、es6 iterables でこれを行うためのより良い方法があります)。


ここにワンライナーがあります:

function zip(arrays) {
    return arrays[0].map(function(_,i){
        return arrays.map(function(array){return array[i]})
    });
}

// > zip([[1,2],[11,22],[111,222]])
// [[1,11,111],[2,22,222]]]

// If you believe the following is a valid return value:
//   > zip([])
//   []
// then you can special-case it, or just do
//  return arrays.length==0 ? [] : arrays[0].map(...)

上記は、配列が同じサイズであることを前提としています。また、引数リストが可変長である Python のバージョンとは異なり、リスト引数の単一のリストを渡すことも前提としています。これらすべての「機能」が必要な場合は、以下を参照してください。約 2 行の追加コードが必要です。

以下は、配列のサイズが等しくないエッジ ケースでの Python の動作を模倣zipし、配列の長い部分が存在しないふりを静かに行います。

function zip() {
    var args = [].slice.call(arguments);
    var shortest = args.length==0 ? [] : args.reduce(function(a,b){
        return a.length<b.length ? a : b
    });

    return shortest.map(function(_,i){
        return args.map(function(array){return array[i]})
    });
}

// > zip([1,2],[11,22],[111,222,333])
// [[1,11,111],[2,22,222]]]

// > zip()
// []

これは Python の動作を模倣し、配列が定義されていない場所itertools.zip_longestに挿入します。undefined

function zip() {
    var args = [].slice.call(arguments);
    var longest = args.reduce(function(a,b){
        return a.length>b.length ? a : b
    }, []);

    return longest.map(function(_,i){
        return args.map(function(array){return array[i]})
    });
}

// > zip([1,2],[11,22],[111,222,333])
// [[1,11,111],[2,22,222],[null,null,333]]

// > zip()
// []

これらの最後の 2 つのバージョン (variadic aka. multiple-argument バージョン) を使用すると、zip はそれ自体の逆ではなくなります。zip(*[...])Python のイディオムを模倣するにzip.apply(this, [...])は、zip 関数を逆にしたい場合、または同様に可変数のリストを入力として持ちたい場合に行う必要があります。


補遺:

このハンドルを反復可能にするには (たとえば、Python ではzip文字列、範囲、マップ オブジェクトなどで使用できます)、次のように定義できます。

function iterView(iterable) {
    // returns an array equivalent to the iterable
}

ただしzip、次のように記述すれば、それも必要ありません。

function zip(arrays) {
    return Array.apply(null,Array(arrays[0].length)).map(function(_,i){
        return arrays.map(function(array){return array[i]})
    });
}

デモ:

> JSON.stringify( zip(['abcde',[1,2,3,4,5]]) )
[["a",1],["b",2],["c",3],["d",4],["e",5]]

(または、range(...)Python スタイルの関数を既に作成している場合は、それを使用することもできます。最終的には、ECMAScript 配列内包表記またはジェネレーターを使用できるようになります。)

于 2012-04-23T15:58:42.350 に答える
45

ライブラリUnderscoreを確認してください。

Underscore は、map、filter、invoke などの日常的な関数ヘルパーと、関数バインド、JavaScript テンプレート、クイック インデックスの作成、詳細な等価性テストなどのより専門的な機能の両方をサポートする 100 を超える関数を提供します。

– それを作った人々を言う

私は最近、特にzip()機能のためにそれを使い始めましたが、素晴らしい第一印象を残しました. 私は jQuery と CoffeeScript を使用していますが、それらと完全に調和しています。アンダースコアは、中断したところから再開され、今のところがっかりすることはありません。あ、ちなみに3kbしか縮小されていません。

見てみな:

_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
// returns [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]
于 2011-08-31T16:53:42.207 に答える
18

ninjagecko の優れた包括的な回答に加えて、2 つの JS 配列を「タプルミミック」に圧縮するために必要なことは次のとおりです。

//Arrays: aIn, aOut
Array.prototype.map.call( aIn, function(e,i){return [e, aOut[i]];})

説明:
Javascript にはtuples型がないため、タプル、リスト、およびセットの関数は、言語仕様では優先度が高くありませんでした。それ以外の場合は、JS >1.6 の Array map を
介して、同様の動作に簡単にアクセスできます。(指定されていないにもかかわらず、多くの >JS 1.4 エンジンで JS エンジン メーカーによって実際に実装されることがよくあります)。関数引数が必要なため、 Python の, ,... との主な違いは、の関数型スタイルに起因します。さらに、これは-instance の機能です。入力の余分な宣言が問題になる場合は、代わりに使用できます。map
zipizipmapmapArrayArray.prototype.map

例:

_tarrin = [0..constructor, function(){}, false, undefined, '', 100, 123.324,
         2343243243242343242354365476453654625345345, 'sdf23423dsfsdf',
         'sdf2324.234dfs','234,234fsf','100,100','100.100']
_parseInt = function(i){return parseInt(i);}
_tarrout = _tarrin.map(_parseInt)
_tarrin.map(function(e,i,a){return [e, _tarrout[i]]})

結果:

//'('+_tarrin.map(function(e,i,a){return [e, _tarrout[i]]}).join('),\n(')+')'
>>
(function Number() { [native code] },NaN),
(function (){},NaN),
(false,NaN),
(,NaN),
(,NaN),
(100,100),
(123.324,123),
(2.3432432432423434e+42,2),
(sdf23423dsfsdf,NaN),
(sdf2324.234dfs,NaN),
(234,234fsf,234),
(100,100,100),
(100.100,100)

関連するパフォーマンス:

mapオーバーループの使用for:

参照: [1,2] と [7,8] を [[1,7], [2,8]] にマージする最も効率的な方法は何ですか?

圧縮テスト

注:falseやなどの基本型はundefined、プロトタイプのオブジェクト階層を持たないため、toString関数を公開しません。したがって、これらは出力で空として表示されます。の 2 番目の引数は基数/基数であり、数値の変換先であり、引数関数の 2 番目の引数としてインデックスを渡すため、ラッパー関数が使用されます
parseIntmap

于 2013-07-28T11:58:58.010 に答える
4

Javascript自体には組み込まれていません。一般的なJavascriptフレームワーク(プロトタイプなど)のいくつかは実装を提供しますが、独自に作成することもできます。

于 2011-01-31T22:11:47.197 に答える
4

1.Npm モジュール:zip-array

Python の JavaScript バージョンとして使用できる npm モジュールを見つけましたzip

zip-array - Python の zip 関数に相当する JavaScript. 各配列の値をマージします。

https://www.npmjs.com/package/zip-array

2. tf.data.zip()Tensorflow.js で

もう 1 つの選択肢は、Tensorflow.js ユーザー向けですzip。Javascript で tensorflow データセットを操作するために Python で関数が必要な場合は、Tensorflow.js で使用できますtf.data.zip()

ここに文書化されているTensorflow.js の tf.data.zip()

于 2019-03-06T08:07:02.330 に答える
3

@Brandon のように、Underscorezip関数をお勧めします。ただし、 のように動作し、必要に応じて値をzip_longest追加undefinedして、最長の入力の長さを返します。

このメソッドを使用して、mixinアンダースコアを で拡張しましたzipShortest。これzip、ライブラリの独自のzip.

以下を一般的な JS コードに追加して、アンダースコアの一部であるかのように呼び出すことができます:_.zipShortest([1,2,3], ['a'])たとえば[[1, 'a']]、 return 。

// Underscore library addition - zip like python does, dominated by the shortest list
//  The default injects undefineds to match the length of the longest list.
_.mixin({
    zipShortest : function() {
        var args = Array.Prototype.slice.call(arguments);
        var length = _.min(_.pluck(args, 'length')); // changed max to min
        var results = new Array(length);
        for (var i = 0; i < length; i++) {
            results[i] = _.pluck(args, "" + i);
        }
        return results;
}});
于 2012-11-29T03:34:15.247 に答える
2

上記のプラグインがどのように機能するのか疑問に思って、純粋な JS でこれを実行しました。これが私の結果です。これがIEなどでどれほど安定するかはわかりません。簡単なモックアップです。

init();

function init() {
    var one = [0, 1, 2, 3];
    var two = [4, 5, 6, 7];
    var three = [8, 9, 10, 11, 12];
    var four = zip(one, two, one);
    //returns array
    //four = zip(one, two, three);
    //returns false since three.length !== two.length
    console.log(four);
}

function zip() {
    for (var i = 0; i < arguments.length; i++) {
        if (!arguments[i].length || !arguments.toString()) {
            return false;
        }
        if (i >= 1) {
            if (arguments[i].length !== arguments[i - 1].length) {
                return false;
            }
        }
    }
    var zipped = [];
    for (var j = 0; j < arguments[0].length; j++) {
        var toBeZipped = [];
        for (var k = 0; k < arguments.length; k++) {
            toBeZipped.push(arguments[k][j]);
        }
        zipped.push(toBeZipped);
    }
    return zipped;
}

防弾ではありませんが、それでも面白いです。

于 2011-01-31T22:46:55.830 に答える
1

ジッパー機能を提供するオプションを使用して、そうするための簡単な機能を作成しました

function zip(zipper, ...arrays) {
    if (zipper instanceof Array) {
        arrays.unshift(zipper)
        zipper = (...elements) => elements
    }

    const length = Math.min(...arrays.map(array => array.length))
    const zipped = []

    for (let i = 0; i < length; i++) {
        zipped.push(zipper(...arrays.map(array => array[i])))
    }

    return zipped
}

https://gist.github.com/AmrIKhudair/4b740149c29c492859e00f451832975b

于 2021-01-22T12:43:41.040 に答える
0

Mochikitライブラリは、これと他の多くの Python のような関数を提供します。Mochikit の開発者は Python ファンでもあるため、Python の一般的なスタイルを持ち、ねじれたようなフレームワークで非同期呼び出しをラップします。

于 2011-01-31T22:25:10.913 に答える
0

同等の機能はありません。少数の配列しかない場合は、forループを使用してインデックスを取得し、そのインデックスを使用して配列にアクセスする必要があります。

var array1 = [1, 2, 3];
var array2 = ['a','b','c'];

for (let i = 0; i < Math.min(array1.length, array2.length); i++) {
    doStuff(array1[i], array2[i]);
}

もっとある場合は、配列に内部ループを設定できます。

于 2021-01-22T15:43:21.467 に答える