(и FizzyTea указывает, что ES6 имеет синтаксис переменных аргументов, поэтому следующее определение функции будет действовать как python, но смотрите Ниже об отказе от ответственности... это не будет ее собственным обратным, поэтому zip(zip(x)) не будет равно x; хотя, как указывает Мэтт Крамер 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
(Обратите внимание, что у ... синтаксиса могут быть проблемы с производительностью в настоящее время и, возможно, в будущем, поэтому, если вы используете второй ответ с переменными аргументами, вы можете захотеть протестировать его на совершенство. Тем не менее, прошло довольно много времени с тех пор, как она была в стандарте.)
Обязательно обратите внимание на дополнение, если вы хотите использовать это для строк (возможно, сейчас есть лучший способ сделать это с помощью es6 iterables).
// 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(...)
Вышесказанное предполагает, что массивы имеют одинаковый размер, как и должно быть. Также предполагается, что вы передаете один аргумент list of lists , в отличие от версии Python, где список аргументов является переменным. Если вам нужны все эти "возможности", смотрите Ниже. Это займет всего около 2 дополнительных строк кода.
Следующее будет имитировать поведение Python zip в крайних случаях, когда массивы неодинакового размера, молчаливо притворяясь, что более длинные части массивов не существуют:
functionzip() { var args = [].slice.call(arguments); var shortest = args.length==0 ? [] : args.reduce(function(a,b){ return a.length<b.length ? a : b });
Если вы используете эти последние две версии (также известные как variadic. версии с несколькими аргументами), то zip больше не является собственной инверсией. Чтобы имитировать zip(*[...]) идиому из Python, вам нужно будет сделать zip.apply(this, [...]) когда вы хотите инвертировать zip-функцию или если вы хотите аналогичным образом иметь переменное количество списков в качестве входных данных.
дополнение:
Чтобы сделать эту обработку любой итеративной (например, в Python вы можете использовать zip для строк, диапазонов, объектов карты и т.д.), Вы могли бы определить следующее:
functioniterView(iterable) { // returns an array equivalent to the iterable }
Однако, если вы напишете zip следующим способом, даже в этом не будет необходимости:
(Или вы могли бы использовать range(...) функцию в стиле Python, если вы ее уже написали. В конечном итоге вы сможете использовать интерпретаторы массивов ECMAScript или генераторы.)
Underscore предоставляет более 100 функций, которые поддерживают как ваши любимые функциональные помощники в повседневной работе: map, filter, invoke, так и более специализированные функции: привязку функций, создание шаблонов javascript, быстрое создание индексов, глубокое тестирование на равенство и так далее.
– Скажите, кто это сделал
Недавно я начал использовать его специально для zip() функции, и это произвело отличное первое впечатление. Я использую jQuery и CoffeeScript, и это просто идеально сочетается с ними. Подчеркивание начинается с того места, где они заканчиваются, и до сих пор оно меня не подводило. Да, кстати, уменьшено всего на 3 КБ.
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 elseyield results.map(res => res.value ) } }
Сначала мы получаем список итераций в виде iterators. Обычно это происходит прозрачно, но здесь мы делаем это явно, поскольку выдаем пошагово, пока один из них не будет исчерпан. Мы проверяем, исчерпан ли какой-либо из результатов (используя .some() метод) в данном массиве, и если это так, мы прерываем цикл while.
Ответ 4
В дополнение к превосходному и всеобъемлющему ответу ninjagecko, все, что требуется, чтобы сжать два JS-массива в "имитацию кортежа", это:
Объяснение: Поскольку Javascript не имеет tuples типа, функции для кортежей, списков и наборов не были высокоприоритетными в спецификации языка. В остальном аналогичное поведение доступно простым способом через отображение массива в JS > 1.6. (map на самом деле часто реализуется производителями движков JS во многих движках > JS 1.4, несмотря на то, что это не указано). Основное отличие от Python zip, izip, ... вытекает из map функционального стиля, поскольку map требуется функция-аргумент. Кроме того, это функция Array-экземпляра. Вместо этого можно использовать Array.prototype.map, если проблема с дополнительным объявлением для ввода.
Примечание: базовые типы, такие как false и undefined, не содержат прототипной иерархии объектов и, следовательно, не предоставляют toString функцию. Следовательно, в выходных данных они отображаются как пустые. В качестве parseInt второго аргумента используется основание / number radix , в которое нужно преобразовать число, и поскольку map передает индекс в качестве второго аргумента своей функции-аргумента, используется функция-оболочка.