Skip to content
This repository has been archived by the owner on Sep 1, 2020. It is now read-only.

WIP: Added 'order' keyword argument to cartesian product #40

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
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,9 @@ Install this package with `Pkg.add("Iterators")`
i = 'c'
```

- **product**(xs...)
- **product**(xs..., [order])

Iterate over all combinations in the cartesian product of the inputs.
Iterate over all combinations in the cartesian product of the inputs. The `order` keyword argument specifies whether the elements are traversed in lexicographic order (`false`) or anti-lexicographic order (`true`, the default value).

Example:
```julia
Expand All @@ -171,6 +171,21 @@ Install this package with `Pkg.add("Iterators")`
p = (2,2)
p = (3,2)
```
while
```julia
for p in product(1:3,1:2,order=false)
@show p
end
```
yields
```
p = (1,1)
p = (1,2)
p = (2,1)
p = (2,2)
p = (3,1)
p = (3,2)
```


- **distinct**(xs)
Expand Down
37 changes: 29 additions & 8 deletions src/Iterators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ export
imap,
subsets,
iterate,
@itr
@itr,
AntiLexicographicOrder,
LexicographicOrder

# Infinite counting

Expand Down Expand Up @@ -258,17 +260,30 @@ done(it::Chain, state) = state[1] > length(it.xss)

# Cartesian product as a sequence of tuples

immutable Product
abstract SortingOrder

abstract LexicographicOrder <: SortingOrder
abstract AntiLexicographicOrder <: SortingOrder

immutable Product{order}
xss::Vector{Any}
function Product(xss...)
new(Any[xss...])
end
Product(xss...)=new(Any[xss...])
end


eltype(p::Product) = tuple(map(eltype, p.xss)...)
length(p::Product) = prod(map(length, p.xss))

product(xss...) = Product(xss...)
function product(xss...; order=AntiLexicographicOrder)
if order==AntiLexicographicOrder
Product{order}(xss...)
elseif order==LexicographicOrder
Product{order}(reverse(xss)...)
else
error("Order '$(order)' unsupported")
Product{order}(xss...)
end
end

function start(it::Product)
n = length(it.xss)
Expand All @@ -288,10 +303,16 @@ function start(it::Product)
return js, vs
end

function next(it::Product, state)
function next{T}(it::Product{T}, state)
js = copy(state[1])
vs = copy(state[2])
ans = tuple(vs...)
ans = if T==AntiLexicographicOrder
tuple(vs...)
elseif T==LexicographicOrder
tuple(reverse(vs)...)
else
error("Ordering '$(T)' not supported")
end

n = length(it.xss)
for i in 1:n
Expand Down
2 changes: 2 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ x1 = 1:2:10
x2 = 1:5
@test collect(product(x1, x2)) == vec([(y1, y2) for y1 in x1, y2 in x2])

@test collect(product(x1, x2, order=LexicographicOrder)) == vec([(y1, y2) for y2 in x2, y1 in x1])

# distinct
# --------

Expand Down