# How to sum tuple elements

`x` is a matrix 5x5 of tuples. How can I filter the tuples where the sum of their elements is 6?

``````numbers = [1,2,3,4,5]
x = collect(Iterators.product(numbers, numbers))
``````

Maybe

``````julia> x = collect(Iterators.product(numbers, numbers))
5×5 Matrix{Tuple{Int64, Int64}}:
(1, 1)  (1, 2)  (1, 3)  (1, 4)  (1, 5)
(2, 1)  (2, 2)  (2, 3)  (2, 4)  (2, 5)
(3, 1)  (3, 2)  (3, 3)  (3, 4)  (3, 5)
(4, 1)  (4, 2)  (4, 3)  (4, 4)  (4, 5)
(5, 1)  (5, 2)  (5, 3)  (5, 4)  (5, 5)

julia> (x -> sum(x) .== 6).(x)
5×5 BitMatrix:
0  0  0  0  1
0  0  0  1  0
0  0  1  0  0
0  1  0  0  0
1  0  0  0  0
``````

?

1 Like

OK. But how can filter the tuples that have value `1`? Like (1, 5), (2, 4), …
I tried to use:
`y = filter((x -> sum(x) .== 6 .x), x)`
but I got an error.

``````julia> x = [ (1,2) (2,4)
(1,1) (1,5) ]
2×2 Matrix{Tuple{Int64, Int64}}:
(1, 2)  (2, 4)
(1, 1)  (1, 5)

julia> filter(t -> sum(t) == 6, x)
2-element Vector{Tuple{Int64, Int64}}:
(2, 4)
(1, 5)

``````
1 Like

@leandromartinez98 Sorry, your solution gives an error.
I don’t understand why the complete solution gives an error:

``````numbers = [1,2,3,4,5]
x = collect(Iterators.product(numbers, numbers))
y = filter(t -> sum(t) == 6, x)
``````

It doesn’t here, just copying and pasting your code:

``````julia
_
_       _ _(_)_     |  Documentation: https://docs.julialang.org
(_)     | (_) (_)    |
_ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` |  |
| | |_| | | | (_| |  |  Version 1.6.2 (2021-07-14)
_/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> numbers = [1,2,3,4,5]
5-element Vector{Int64}:
1
2
3
4
5

julia> x = collect(Iterators.product(numbers, numbers))
5×5 Matrix{Tuple{Int64, Int64}}:
(1, 1)  (1, 2)  (1, 3)  (1, 4)  (1, 5)
(2, 1)  (2, 2)  (2, 3)  (2, 4)  (2, 5)
(3, 1)  (3, 2)  (3, 3)  (3, 4)  (3, 5)
(4, 1)  (4, 2)  (4, 3)  (4, 4)  (4, 5)
(5, 1)  (5, 2)  (5, 3)  (5, 4)  (5, 5)

julia> y = filter(t -> sum(t) == 6, x)
5-element Vector{Tuple{Int64, Int64}}:
(5, 1)
(4, 2)
(3, 3)
(2, 4)
(1, 5)

julia>

``````
3 Likes

If you `filter`, what kind of shape do you expect the object to have? It’s a matrix, what does it mean to just get rid of elements in the matrix?

Sorry, you’re right. I must have done something wrong.
It is OK in the REPL but in Vscode gives the error `MethodError: objects of type Int64 are not callable`.

You’re right. But I am only interested in some elements of the matrix and I want to list them.

FWIW, if you don’t care of a matrix shape and only want the tuples which give the sum 6, then you may rewrite your code without `collect`ing the product:

``````julia> numbers = 1:5;

julia> x = Iterators.product(numbers, numbers); # or x = ((k, l) for k in numbers for l in numbers)

julia> ts = [tup for tup in x if sum(tup) == 6]
5-element Vector{Tuple{Int64, Int64}}:
(5, 1)
(4, 2)
(3, 3)
(2, 4)
(1, 5)
``````

The same can be written as `ts = collect(Iterators.filter(tup -> sum(tup) == 6, x))` but doesn’t work for eager `filter` (looks like `filter` isn’t defined for lazy iterables).

3 Likes

Here is what I learnt, where an error said some type “are not callable”, there is somewhere in your code you used a function name as variable.

For example:

``````               _
_       _ _(_)_     |  Documentation: https://docs.julialang.org
(_)     | (_) (_)    |
_ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` |  |
| | |_| | | | (_| |  |  Version 1.4.2 (2020-05-23)
_/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> sum  = 6
6

julia> sum([1,2])
ERROR: MethodError: objects of type Int64 are not callable
Stacktrace:
 top-level scope at REPL:1

``````
1 Like

Thank you. I had a variable called `sum` in `Vscode` but not in REPL.

What do you mean for `eager filter`?

`Base.filter` is eager, i.e. it produces all the values once called.
`Iterators.filter` is lazy, i.e. it produces the values one by one on demand.

Because of that, `Base.filter` is not defined for an arbitrary iterable, only for certain types which are guaranteed to have a finite length. And, as it turns out, it doesn’t work with generators. `Iterators.filter` works with any iterable because of laziness.

So, this works:

``````nums = (n for n in 1:10)
evens = [n for n in nums if iseven(n)]
``````

This stops with an error because `Base.filter` doesn’t work with generators (because they potentially may produce an infinite sequence):

``````filter(iseven, nums)
``````
3 Likes

FWIW, some benchmarks with the classical Matlab-like alternative:

``````using BenchmarkTools
f(x,n) = x[sum.(x) .== n]
g(x,n) = filter(t -> sum(t) == n, x)

numbers = 1:100
x = collect(Iterators.product(numbers, numbers))
n = 100
f(x,n) == g(x,n)  # true

@btime f(\$x,\$n)   # 4.4 μs (4 allocations: 7.3 KiB)
@btime g(\$x,\$n)   # 8.7 μs (3 allocations: 156.3 KiB)
``````