Skip to content

zip and gzip method which works like python's itertools.zip and izip. #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions lib/underscore.lua
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,58 @@ end

-- iter

function Underscore.funcs.gzip(left_iter, right_iter)
local left_iter_is_function = type(left_iter) == "function"
local right_iter_is_function = type(right_iter) == "function"

if left_iter_is_function and right_iter_is_function then
return coroutine.wrap(function()
local left_item, right_item = left_iter(), right_iter()
while left_item ~= nil and right_item ~= nil do
coroutine.yield(left_item, right_iter)
left_item, right_item = left_iter(), right_iter()
end
end)
elseif left_iter_is_function then
return coroutine.wrap(function()
local i = 1
local left_item , right_item, i = left_iter(), right_iter[i], i + 1
while left_item ~= nil and right_item ~= nil do
coroutine.yield(left_item, right_item)
left_item , right_item, i = left_iter(), right_iter[i], i + 1
end
end)
elseif right_iter_is_function then
return coroutine.wrap(function()
local i = 1
local left_item , right_item, i = left_iter[i], right_iter(), i + 1
while left_item ~= nil and right_item ~= nil do
coroutine.yield(left_item, right_item)
left_item , right_item, i = left_iter[i], right_iter(), i + 1
end
end)
else
return coroutine.wrap(function()
local i = 1
local left_item, right_item, i = left_iter[i], right_iter[i], i + 1
while left_item ~= nil and right_item ~= nil do
coroutine.yield(left_item, right_item)
left_item, right_item, i = left_iter[i], right_iter[i], i + 1
end
end)
end
end

function Underscore.funcs.zip(left_iter, right_iter)
local zipped = {}
local i = 1
for left_item, right_item in Underscore.funcs.gzip(left_iter, right_iter) do
zipped[i] = {left_item, right_item}
i = i + 1
end
return zipped
end

function Underscore.funcs.each(list, func)
for i in Underscore.iter(list) do
func(i)
Expand Down
2 changes: 2 additions & 0 deletions spec/spec_helper.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
require 'luaspec'
require 'luamock'

package.path = "../lib/?.lua;" .. package.path
_ = require 'underscore'

function matchers.should_equal(value, expected)
Expand Down
205 changes: 205 additions & 0 deletions spec/zip_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
require 'spec_helper'

describe["_.zip"] = function()
describe["*** when providing two lists ***"] = function()
describe["when both lists are of equal length"] = function()
before = function()
left_list = {1, 3, 5}
right_list = {2, 4, 6}
result = _.zip(left_list, right_list)
end

it["should return {{1,2}, {3,4}, {5,6}}"] = function()
expect(
result[1][1] == 1 and
result[1][2] == 2 and
result[2][1] == 3 and
result[2][2] == 4 and
result[3][1] == 5 and
result[3][2] == 6
).should_be(true)
end
end

describe["when the left list is shorter than the right"] = function()
before = function()
left_list = {1, 3, 5}
right_list = {2, 4, 6, 7}
result = _.zip(left_list, right_list)
end

it["\tshould return {{1,2}, {3,4}, {5,6}}"] = function()
expect(
result[1][1] == 1 and
result[1][2] == 2 and
result[2][1] == 3 and
result[2][2] == 4 and
result[3][1] == 5 and
result[3][2] == 6
).should_be(true)
end
end

describe["when the left list is longer than the right"] = function()
before = function()
left_list = {1, 3, 5, 7}
right_list = {2, 4, 6}
result = _.zip(left_list, right_list)
end

it["should return {{1,2}, {3,4}, {5,6}}"] = function()
expect(
result[1][1] == 1 and
result[1][2] == 2 and
result[2][1] == 3 and
result[2][2] == 4 and
result[3][1] == 5 and
result[3][2] == 6
).should_be(true)
end
end
end

describe["*** when left is function, right a list ***"] = function()
describe["when the left function will yield the SAME number of values as the right list"] = function()
before = function()
left_func = coroutine.wrap(function()
for i=1, 5, 2 do
coroutine.yield(i)
end
end)
right_list = {2, 4, 6}
result = _.zip(left_func, right_list)
end

it["should return {{1,2}, {3,4}, {5,6}}"] = function()
expect(
result[1][1] == 1 and
result[1][2] == 2 and
result[2][1] == 3 and
result[2][2] == 4 and
result[3][1] == 5 and
result[3][2] == 6
).should_be(true)
end
end

describe["when the left function will yield LESS values as the right list"] = function()
before = function()
left_func = coroutine.wrap(function()
for i=1, 5, 2 do
coroutine.yield(i)
end
end)
right_list = {2, 4, 6, 7}
result = _.zip(left_func, right_list)
end

it["should return {{1,2}, {3,4}, {5,6}}"] = function()
expect(
result[1][1] == 1 and
result[1][2] == 2 and
result[2][1] == 3 and
result[2][2] == 4 and
result[3][1] == 5 and
result[3][2] == 6
).should_be(true)
end
end

describe["when the left function will yield MORE values as the right list"] = function()
before = function()
left_func = coroutine.wrap(function()
for i=1, 7, 2 do
coroutine.yield(i)
end
end)
right_list = {2, 4, 6}
result = _.zip(left_func, right_list)
end

it["should return {{1,2}, {3,4}, {5,6}}"] = function()
expect(
result[1][1] == 1 and
result[1][2] == 2 and
result[2][1] == 3 and
result[2][2] == 4 and
result[3][1] == 5 and
result[3][2] == 6
).should_be(true)
end
end
end

describe["*** when right is function, left a list ***"] = function()
describe["when the right function will yield the same number of values as the left list"] = function()
before = function()
local left_list = {1, 3, 5}
local right_func = coroutine.wrap(function()
for i=2, 6, 2 do
coroutine.yield(i)
end
end)
result = _.zip(left_list, right_func)
end

it["should return {{1,2}, {3,4}, {5,6}}"] = function()
expect(
result[1][1] == 1 and
result[1][2] == 2 and
result[2][1] == 3 and
result[2][2] == 4 and
result[3][1] == 5 and
result[3][2] == 6
).should_be(true)
end
end

describe["when the right function will yield LESS values as the left list"] = function()
before = function()
local left_list = {1, 3, 5}
local right_func = coroutine.wrap(function()
for i=2, 4, 2 do
coroutine.yield(i)
end
end)
result = _.zip(left_list, right_func)
end

it["should return {{1,2}, {3,4}}"] = function()
expect(
result[1][1] == 1 and
result[1][2] == 2 and
result[2][1] == 3 and
result[2][2] == 4
).should_be(true)
end
end

describe["when the right function will yield MORE values as the left list"] = function()
before = function()
local left_list = {1, 3, 5}
local right_func = coroutine.wrap(function()
for i=2,8,2 do
coroutine.yield(i)
end
end)
result = _.zip(left_list, right_func)
end

it["should return {{1,2}, {3,4}, {5,6}}"] = function()
expect(
result[1][1] == 1 and
result[1][2] == 2 and
result[2][1] == 3 and
result[2][2] == 4 and
result[3][1] == 5 and
result[3][2] == 6
).should_be(true)
end
end
end
end


spec:report(true)