Javascript เทียบเท่ากับฟังก์ชั่น zip ของ Python


216

มีฟังก์ชัน javascript ที่เทียบเท่ากับฟังก์ชัน zip ของ Python หรือไม่ นั่นคือให้หลายอาร์เรย์ที่มีความยาวเท่ากันสร้างอาร์เรย์ของคู่

ตัวอย่างเช่นถ้าฉันมีสามอาร์เรย์ที่มีลักษณะเช่นนี้:

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]]

5
มันยุติธรรมหรือไม่ที่จะบอกว่าเราผู้เขียนโปรแกรม Python นั้นกลัววิธีโง่ที่เกี่ยวข้องกับลูปเพราะมันช้าและมักจะมองหาวิธีการในตัวในการทำสิ่งต่าง ๆ แต่นั่นใน Javascript เราควรลงมือเขียนและลูปของเราเพราะมันไม่ได้ช้าโดยเฉพาะ?
LondonRob

3
@LondonRob การวนซ้ำเป็นการวนที่ซ่อนอยู่หลังเมธอด 'fast' หรือไม่ JavaScript ได้รับแน่นอนได้รับการสนับสนุนมากขึ้นสำหรับฟังก์ชั่นการสั่งซื้อที่สูงขึ้นด้วยการแนะนำของอาเรย์forEach, reduce, map, everyฯลฯ มันเป็นเพียงกรณีที่zipไม่ได้ "ทำให้ตัด" (กflatMapนี้ยังขาด) ไม่ได้สำหรับการพิจารณาประสิทธิภาพ - แต่ เพื่อความเป็นธรรม. NET (3.5) ไม่มี Zip on Enumerable เป็นเวลาสองปี! ไลบรารี 'functionalish' ใด ๆ เช่นขีดล่าง / lodash (lodash 3.x มีการประเมินผลตามลำดับที่ขี้เกียจ) จะให้ฟังก์ชันซิปที่เทียบเท่า
2864740

@ user2864740 ตีความห่วง (เช่นในหลาม) มักจะเป็นมากช้ากว่าห่วงรหัสเครื่อง คอมไพล์ JIT ที่คอมไพล์แล้ว (เช่นในเอ็นจิน JS สมัยใหม่) อาจเข้าใกล้ความเร็วซีพียูดั้งเดิมมากจนได้รับการแนะนำโดยใช้ลูปโค้ดเครื่องอาจถูกชดเชยโดยโอเวอร์เฮดของการเรียกใช้ฟังก์ชันที่ไม่ระบุชื่อ ถึงกระนั้นมันก็สมเหตุสมผลที่จะมีฟังก์ชั่นในตัวเหล่านี้และเพื่อแสดงรูปแบบต่างๆของ "วงใน" ของคุณด้วยเอ็นจิน JS หลายตัว ผลลัพธ์อาจไม่ชัดเจน
Tobia

คำตอบ:


178

อัพเดท 2016:

ต่อไปนี้เป็นรุ่น Snazzier 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 มีไวยากรณ์อาร์กิวเมนต์ variadic ดังนั้นนิยามฟังก์ชันต่อไปนี้จะทำหน้าที่เหมือนงูหลาม แต่ดูด้านล่างสำหรับข้อจำกัดความรับผิดชอบ ... นี้จะไม่เป็นสิ่งที่ตรงกันข้ามของตัวเองดังนั้นzip(zip(x))จะไม่เท่ากันx; แม้ในขณะที่แมตต์เครเมอชี้ให้เห็นzip(...zip(...x))==x(เช่น ในงูหลามปกติzip(*zip(*x))==x))

ทางเลือกคำนิยาม equiv ถึง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

(โปรดทราบว่า...ไวยากรณ์อาจมีปัญหาด้านประสิทธิภาพในเวลานี้และอาจเป็นไปได้ในอนาคตดังนั้นหากคุณใช้คำตอบที่สองพร้อมกับข้อโต้แย้งหลากหลายคุณอาจต้องการทดสอบมัน)


นี่คือผู้เผยแพร่:

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 ที่รายการอาร์กิวเมนต์เป็น Variadic หากคุณต้องการ "คุณสมบัติ" ทั้งหมดเหล่านี้ดูด้านล่าง ใช้รหัสพิเศษอีกประมาณ 2 บรรทัด

ต่อไปนี้จะเลียนแบบ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()
// []

สิ่งนี้จะเลียนแบบ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()
// []

หากคุณใช้สองเวอร์ชันล่าสุด (ผันแปร aka รุ่นหลายอาร์กิวเมนต์หลายตัว) zip จะไม่ตรงกันข้ามของมันเอง ในการเลียนแบบzip(*[...])สำนวนจาก Python คุณจะต้องทำzip.apply(this, [...])เมื่อคุณต้องการสลับฟังก์ชั่น zip หรือถ้าคุณต้องการให้จำนวนรายการที่หลากหลายเป็นอินพุตเหมือนกัน


ภาคผนวก :

เพื่อให้การจัดการนี้ iterable ใด ๆ (เช่นใน 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-style ถ้าคุณเขียนไปแล้วในที่สุดคุณจะสามารถใช้ ECMAScript array comprehensions หรือ Generators)


1
สิ่งนี้ไม่ได้ผลสำหรับฉัน: TypeError: Object 1 ไม่มีเมธอด 'map'
Emanuele Paolini

7
และ ES6 สำหรับ arad variadic และ iterable ใด ๆ :zip = (...rows) => [...rows[0]].map((_,c) => rows.map(row => row[c]));
1983

"Object 1 ไม่มีเมธอด 'map'" อาจเป็นกรณีของการพยายามใช้สิ่งนี้กับวัตถุที่ไม่มีเมธอด map (เช่น nodelist หรือ string) ซึ่งอยู่ในภาคผนวกของบทความนี้
ninjagecko

ในขณะที่มันเป็นความจริงที่ว่ารุ่น ES6 variadic ไม่รักษาคุณยังสามารถได้รับความสุขในความเชื่อมั่นว่าzip(zip(x)) = x zip(...zip(...x)) = x
Matt Kramer

const the_longest_array_length = Math.max(...(arrays.map(array => array.length)));
КонстантинВан

34

ลองดูขีดล่างของไลบรารี

ขีดล่างมีฟังก์ชั่นมากกว่า 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]]

3
เมื่อใช้ Underscore คุณจะรู้สึกใกล้ชิดกับความชัดเจนและความผาสุกของ Haskell เล็กน้อย
CamilB

12
แทนการขีดเส้นใต้ให้ลองสิ่งนี้: lodash.com - การแทนที่แบบดรอปอิน, รสชาติที่ดีเหมือนกัน, คุณสมบัติเพิ่มเติม, ความสอดคล้องข้ามเบราว์เซอร์ที่มากขึ้น ดูkitcambridge.be/blog/say-hello-to-lo-dashสำหรับคำอธิบาย
Merlyn Morgan-Graham

16

นอกเหนือจากคำตอบที่ยอดเยี่ยมและครอบคลุมของ Ninjagecko แล้วสิ่งที่ต้องทำก็คือการบีบให้ JS-arrays สองตัวเป็น "tuple-mimic" คือ:

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

คำอธิบาย:
เนื่องจาก Javascript ไม่มีtuplesประเภทฟังก์ชันสำหรับ tuples รายการและชุดจึงไม่ได้มีความสำคัญสูงในข้อกำหนดภาษา
มิฉะนั้นพฤติกรรมคล้ายกันคือสามารถเข้าถึงได้ในลักษณะที่ตรงไปตรงมาผ่านทางแผนที่อาร์เรย์ใน JS> ( mapมักใช้งานจริงโดยผู้สร้างโปรแกรม JS ในหลาย ๆ เครื่องมือ> JS 1.4 แม้จะไม่ได้ระบุ)
ความแตกต่างที่สำคัญในการ ธzip, izip... ผลลัพธ์ที่ได้จากmapรูปแบบการทำงาน 's เนื่องจาก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

หมายเหตุ:ประเภทฐานเช่นfalseและundefinedไม่วางตำแหน่งต้นแบบวัตถุลำดับชั้นและทำให้ไม่เปิดเผยtoStringฟังก์ชั่น ดังนั้นสิ่งเหล่านี้จะแสดงว่าว่างเปล่าในผลลัพธ์
เนื่องจากparseIntอาร์กิวเมนต์ที่สองคือฐาน / เลขฐานซึ่งจะแปลงตัวเลขเป็นและตั้งแต่mapผ่านดัชนีเป็นอาร์กิวเมนต์ที่สองไปยังฟังก์ชันอาร์กิวเมนต์ฟังก์ชันจะใช้ฟังก์ชัน wrapper


ตัวอย่างแรกของคุณบอกว่า "aIn ไม่ใช่ฟังก์ชั่น" เมื่อฉันลองใช้ มันใช้งานได้ถ้าฉันเรียกว่า. map จากอาร์เรย์แทนที่จะเป็นต้นแบบ: aIn.map(function(e, i) {return [e, aOut[i]];})เกิดอะไรขึ้น?
Noumenon

1
@Noumenon Array.prototype.mapควรได้รับการArray.prototype.map.callแก้ไขคำตอบ
ผู้ใช้

11

ตัวอย่าง 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 )
    }
}

ครั้งแรกที่เราได้รับรายชื่อของ iterables iteratorsเป็น สิ่งนี้มักจะเกิดขึ้นอย่างโปร่งใส แต่ที่นี่เราทำอย่างชัดเจนในขณะที่เราให้ผลทีละขั้นตอนจนกว่าจะมีหนึ่งในนั้นหมด เราตรวจสอบว่ามีผลลัพธ์ใด ๆ (ใช้.some()วิธีการ) ในอาร์เรย์ที่กำหนดหมดแล้วหรือไม่และถ้าเป็นเช่นนั้นเราจะแยกลูป while


คำตอบนี้อาจใช้คำอธิบายเพิ่มเติม
cmaher

1
เราได้รับรายชื่อตัววนซ้ำจากตัววนซ้ำ สิ่งนี้มักจะเกิดขึ้นอย่างโปร่งใสที่นี่เราทำอย่างชัดเจนในขณะที่เราให้ผลทีละขั้นตอนอย่างใดอย่างหนึ่งของพวกเขาจะหมด ตรวจสอบว่ามีวิธีการใดในนั้น (วิธี. บางส่วน) ในอาร์เรย์หมดหรือไม่และเราขัดจังหวะหากเป็นเช่นนั้น
Dimitris

11

พร้อมกับฟังก์ชั่นอื่น ๆ ที่คล้ายกับงูหลามpythonicเสนอzipฟังก์ชั่นพร้อมสิทธิประโยชน์พิเศษในการคืนค่าการประเมินที่ขี้เกียจ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))];

การเปิดเผยฉันเป็นผู้แต่งและเป็นผู้ดูแลรักษา Pythonic


7

Python มีสองฟังก์ชั่น: zip และ itertools.zip_longest การใช้งานบน JS / ES6 เป็นดังนี้:

การติดตั้ง Python`s zip บน JS / ES6

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, เท็จ, 212], [3, -378, 323], ['a', '337', 433]]

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

[]

การติดตั้ง Python`s zip_longest บน JS / ES6

( 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, ไม่ได้กำหนด], [2, เท็จ, ไม่ได้กำหนด, ไม่ได้กำหนด],
[3, -378, ไม่ได้กำหนด, ไม่ได้กำหนด], ['a', '337', ไม่ได้กำหนด, ไม่ได้กำหนด]]

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

[[1, 667, 111, null], [2, เท็จ, 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

คุณสามารถสร้างฟังก์ชั่นยูทิลิตี้โดยใช้ 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 ]]


4

1. โมดูล Npm: zip-array

ฉันพบโมดูล npm ที่สามารถใช้เป็น python เวอร์ชัน javascript zip:

zip-array - เทียบเท่าจาวาสคริปต์ของฟังก์ชั่น zip ของ Python ผสานค่าของแต่ละอาร์เรย์เข้าด้วยกัน

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

2. tf.data.zip()ใน Tensorflow.js

อีกทางเลือกหนึ่งสำหรับผู้ใช้ Tensorflow.js: หากคุณต้องการzipฟังก์ชั่นใน python เพื่อทำงานกับชุดข้อมูล tensorflow ใน Javascript คุณสามารถใช้tf.data.zip()ใน Tensorflow.js

tf.data.zip ()ใน Tensorflow.js บันทึกไว้ที่นี่


3

ไม่ใช่ในตัวของ Javascript เอง เฟรมเวิร์ก Javascript ทั่วไปบางส่วน (เช่น Prototype) จัดเตรียมการนำไปใช้หรือคุณสามารถเขียนของคุณเอง


1
Link? นอกจากนี้ฉันจะสนใจถ้า jQuery ทำเพราะนั่นคือสิ่งที่ฉันใช้ ...
pq


2
อย่างไรก็ตามโปรดทราบว่า jQuery จะทำงานแตกต่างจาก Python เล็กน้อยเนื่องจากมันส่งคืนออบเจ็กต์ไม่ใช่อาเรย์ ... ดังนั้นจึงไม่สามารถรวมรายการมากกว่า 2 รายการเข้าด้วยกันได้
แอมเบอร์

ถูกต้องผู้เขียนไม่ควรเรียก jQuery หนึ่งตัวที่เทียบเท่ากัน
pq

3

เช่นเดียวกับ @Brandon ฉันขอแนะนำฟังก์ชันซิปของUnderscore อย่างไรก็ตามมันทำหน้าที่เหมือนการผนวกค่าตามต้องการเพื่อส่งคืนความยาวของอินพุตที่ยาวที่สุดzip_longestundefined

ผมใช้mixinวิธีการที่จะขยายขีดด้วย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;
}});

ลงคะแนนโดยไม่แสดงความคิดเห็น? ฉันยินดีที่จะปรับปรุงคำตอบนี้ แต่ไม่สามารถตอบกลับได้
Pat

2

คุณสามารถลดอาเรย์ของอาเรย์และแมปอาเรย์ใหม่ได้โดยนำผลลัพธ์ของดัชนีของอาเรย์ภายใน

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


1

ชุดรูปแบบของโซลูชันตัวสร้างสันหลังยาว :

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())

และนี่คือสำนวน "n-group" คลาสสิกของงูเหลือมzip(*[iter(a)]*n):

triples = [...zip(...Array(3).fill(iter(a)))]

ฉันสงสัยว่ามีอะไรผิดปกติกับสิ่งนี้ฉันเขียนสิ่งเดียวกัน สำหรับฉันแล้วมันรู้สึกดีกว่าคนอื่น ๆ ทั้งหมด แต่บางทีเราอาจผิดทั้งคู่ ... ฉันกำลังมองหาวิธีเพิ่มประเภทการไหลของมัน แต่ฉันกำลังดิ้นรน: D
cglacet

0

Mochikitห้องสมุดให้นี้และอื่น ๆ อีกมากมายหลามเหมือนฟังก์ชั่น ผู้พัฒนา Mochikit ยังเป็นแฟนตัวยงของ Python ดังนั้นมันจึงเป็นรูปแบบทั่วไปของ Python และทำให้การเรียก async ในกรอบที่คล้ายบิดเป็นเกลียว


0

ฉันใช้เวลากับ 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;
}

มันไม่ได้เป็นกระสุน แต่ก็ยังน่าสนใจ


jsfiddle ดูดี มีปุ่ม TidyUp! ปุ่ม Run ไม่แสดง console.log ของคุณเอาท์พุทในแผงผลลัพธ์ ทำไม?
pq

มัน (console.log) ต้องการบางอย่างเช่น Firebug เพื่อให้ทำงานได้ เพียงแค่เปลี่ยนไปconsole.log alert

บานหน้าต่างผลลัพธ์มีไว้ทำอะไร?
pq

มันแสดงให้เห็นถึง HTML ของซอ ในกรณีนี้ฉันแค่ทำตรง JS นี่คือผลลัพธ์โดยใช้document.write() jsfiddle.net/PyTWw/5

-1

นี่จะเป็นการตัดบรรทัดออกจากคำตอบตามตัววนซ้ำของDdi :

function* zip(...toZip) {
  const iterators = toZip.map((arg) => arg[Symbol.iterator]());
  const next = () => toZip = iterators.map((iter) => iter.next());
  while (next().every((item) => !item.done)) {
    yield toZip.map((item) => item.value);
  }
}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.