web-dev-qa-db-ja.com

PythonのZip関数に相当するJavascript

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]]
185
pq.

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

Underscoreは、マップ、フィルター、起動などのお気に入りの機能ヘルパーをサポートする1​​00以上の関数を提供します。さらに、関数バインディング、javascriptテンプレート、クイックインデックスの作成、完全な等価性テストなど、より特化した機能も提供します。

–それを作った人を言う

最近、 Zip() 関数専用に使用し始めましたが、素晴らしい第一印象を残しました。私はjQueryとCoffeeScriptを使用していますが、それらは完璧に合います。アンダースコアは、彼らが去ったところをすぐに拾い上げ、今のところ私を失望させていません。ちなみに、縮小されたのはわずか3kbです。

見てみな。

30
Brandon

Ninjageckoの優れた総合的な答えに加えて、2つのJSアレイを「タプル模倣」に圧縮するのに必要なことは次のとおりです。

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

説明:
Javascriptにはtuplesタイプがないため、タプル、リスト、およびセットの関数は言語仕様の優先事項ではありませんでした。
それ以外の場合、 JSの配列マップ> 1.6 を使用して、同様の動作に簡単にアクセスできます。 (mapは、指定されていないにも関わらず、多くのJS 1.4エンジンでJSエンジンメーカーによって実際に実装されていることがよくあります)。
PythonのZipizip、...との主な違いは、mapが関数引数を必要とするため、mapの機能スタイルに起因します。さらに、Array- instanceの関数です。入力の追加の宣言が問題である場合は、代わりにArray.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]]にマージする最も効率的な方法

Zip tests

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

14
Lorenz Lo Sauer

他のPythonライクな関数に加えて、 PythonicZip関数を提供し、その動作と同様に、遅延評価 Iterator を返すという追加の利点があります Pythonの同等物

import {Zip, zipLongest} from 'Pythonic';

const arr1 = ['a', 'b'];
const arr2 = ['c', 'd', 'e'];
for (const [first, second] of Zip(arr1, arr2))
    console.log(`first: ${first}, second: ${second}`);
// first: a, second: c
// first: b, second: d

for (const [first, second] of zipLongest(arr1, arr2))
    console.log(`first: ${first}, second: ${second}`);
// first: a, second: c
// first: b, second: d
// first: undefined, second: e

// unzip
const [arrayFirst, arraySecond] = [...Zip(...Zip(arr1, arr2))];

Disclosure私はPythonicの著者であり、メンテナーです

6
Keyvan

Pythonには、Zipとitertools.Zip_longestの2つの関数があります。 JS/ES6での実装は次のようになります。

JS/ES6でのPythonの実装Zip

const Zip = (...arrays) => {
    const length = Math.min(...arrays.map(arr => arr.length));
    return Array.from({ length }, (value, index) => arrays.map((array => array[index])));
};

結果:

console.log(Zip(
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    [11, 221]
));

[[1、667、111、11]]

console.log(Zip(
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111, 212, 323, 433, '1111']
));

[[1、667、111]、[2、false、212]、[3、-378、323]、['a'、 '337'、433]]

console.log(Zip(
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    []
));

[]

JS/ES6でのPythonのZip_longestの実装

https://docs.python.org/3.5/library/itertools.html?highlight=Zip_longest#itertools.Zip_longest

const zipLongest = (placeholder = undefined, ...arrays) => {
    const length = Math.max(...arrays.map(arr => arr.length));
    return Array.from(
        { length }, (value, index) => arrays.map(
            array => array.length - 1 >= index ? array[index] : placeholder
        )
    );
};

結果:

console.log(zipLongest(
    undefined,
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    []
));

[[1、667、111、undefined]、[2、false、undefined、undefined]、
[3、-378、undefined、undefined]、['a'、 '337'、undefined、undefined]]

console.log(zipLongest(
    null,
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    []
));

[[1、667、111、null]、[2、false、null、null]、[3、-378、null、null]、['a'、 '337'、null、null]]

console.log(zipLongest(
    'Is None',
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    []
));

[[1、667、111、 'Is None']、[2、false、 'Is None'、 'Is None']、
[3、-378、 'Is None'、 'Is None']、['a'、 '337'、 'Is None'、 'Is None']]

4
Seti Volkylany

ジェネレーターを使用した最新のES6の例:

function *Zip (...iterables){
    let iterators = iterables.map(i => i[Symbol.iterator]() )
    while (true) {
        let results = iterators.map(iter => iter.next() )
        if (results.some(res => res.done) ) return
        else yield results.map(res => res.value )
    }
}

最初に、iteratorsとしてイテラブルのリストを取得します。通常これは透過的に行われますが、ここでは明示的に行います。そのうちの1つが使い果たされるまで段階的に生成されます。指定された配列の結果(.some()メソッドを使用)が使い果たされているかどうかを確認し、使い果たされている場合は、whileループを中断します。

4
Dimitris

ES6を使用してユーティリティ機能を作成できます。

const Zip = (arr, ...arrs) => {
  return arr.map((val, i) => arrs.reduce((a, arr) => [...a, arr[i]], [val]));
}

// example

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

console.log(Zip(array1, array2));                  // [[1, 'a'], [2, 'b'], [3, 'c']]
console.log(Zip(array1, array2, array3));          // [[1, 'a', 4], [2, 'b', 5], [3, 'c', 6]]

ただし、上記のソリューションでは、最初の配列の長さが出力配列の長さを定義します。

以下に、より詳細に制御できるソリューションを示します。少し複雑ですが、価値があります。

function _Zip(func, args) {
  const iterators = args.map(arr => arr[Symbol.iterator]());
  let iterateInstances = iterators.map((i) => i.next());
  ret = []
  while(iterateInstances[func](it => !it.done)) {
    ret.Push(iterateInstances.map(it => it.value));
    iterateInstances = iterators.map((i) => i.next());
  }
  return ret;
}
const array1 = [1, 2, 3];
const array2 = ['a','b','c'];
const array3 = [4, 5, 6];

const zipShort = (...args) => _Zip('every', args);

const zipLong = (...args) => _Zip('some', args);

console.log(zipShort(array1, array2, array3)) // [[1, 'a', 4], [2, 'b', 5], [3, 'c', 6]]
console.log(zipLong([1,2,3], [4,5,6, 7]))
// [
//  [ 1, 4 ],
//  [ 2, 5 ],
//  [ 3, 6 ],
//  [ undefined, 7 ]]
3
Bhargav Patel

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

python Zipのjavascriptバージョンとして使用できるnpmモジュールを見つけました。

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

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

2. Tensorflow.jsのtf.data.Zip()

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

tf.data.Zip()here で文書化されたTensorflow.jsで

3
Huan

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

3
Amber

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

mixin メソッドを使用して、ライブラリの に基づいてPythonのzipShortestのように動作するZipでアンダースコアを拡張しましたZip の独自のソース。

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

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

内部配列のインデックスの結果を取得することにより、配列の配列を削減し、新しい配列をマッピングできます。

var array1 = [1, 2, 3],
    array2 = ['a','b','c'],
    array3 = [4, 5, 6],
    array = [array1, array2, array3],
    transposed = array.reduce((r, a) => a.map((v, i) => (r[i] || []).concat(v)), []);

console.log(transposed);
2
Nina Scholz

lazy generator solution のバリエーション:

function* iter(it) {
    yield* it;
}

function* Zip(...its) {
    its = its.map(iter);
    while (true) {
        let rs = its.map(it => it.next());
        if (rs.some(r => r.done))
            return;
        yield rs.map(r => r.value);
    }
}

for (let r of Zip([1,2,3], [4,5,6,7], [8,9,0,11,22]))
    console.log(r.join())

// the only change for "longest" is some -> every

function* zipLongest(...its) {
    its = its.map(iter);
    while (true) {
        let rs = its.map(it => it.next());
        if (rs.every(r => r.done))
            return;
        yield rs.map(r => r.value);
    }
}

for (let r of zipLongest([1,2,3], [4,5,6,7], [8,9,0,11,22]))
    console.log(r.join())

そして、これはpythonの古典的な「n-group」イディオムZip(*[iter(a)]*n)です:

triples = [...Zip(...Array(3).fill(iter(a)))]
1
georg

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

0
Keith

私は純粋な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;
}

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

0
user1385191