# Elementwise operation on array of tuples

**URL:** <https://discourse.julialang.org/t/elementwise-operation-on-array-of-tuples/6812>\
**Category:** General Usage\
**Tags:** tuple\
**Created:** [October 31, 2017, 7:47pm UTC](https://discourse.julialang.org/t/elementwise-operation-on-array-of-tuples/6812 "2017-10-31T19:47:23Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![BenjaminBorn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/benjaminborn/32/4910_2.png) [@BenjaminBorn](https://discourse.julialang.org/u/BenjaminBorn)\
**Post date:** [October 31, 2017, 7:47pm UTC](https://discourse.julialang.org/t/elementwise-operation-on-array-of-tuples/6812/1 "2017-10-31T19:47:23Z")

</div>

I can apply `round()` elementwise to tuples as in the following example

```julia
julia> a = (1.234567,7.654321)
(1.234567, 7.654321)

julia> typeof(a)
Tuple{Float64,Float64}

julia> round.(a)
(1.0, 8.0)

```

However, this does not work with arrays of tuples

```julia
julia> b = [a; a]
2-element Array{Tuple{Float64,Float64},1}:
 (1.23457, 7.65432)
 (1.23457, 7.65432)

julia> round.(b)
ERROR: MethodError: no method matching round(::Tuple{Float64,Float64})

```

Is there a convenient way to apply a function to each element of an array of tuples or do I have to write a loop?

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [October 31, 2017, 7:54pm UTC](https://discourse.julialang.org/t/elementwise-operation-on-array-of-tuples/6812/2 "2017-10-31T19:54:49Z")

</div>

map or comprehensions maybe?

```julia
julia> map(x->round.(x), b)                                                                                                                                              
2-element Array{Tuple{Float64,Float64},1}:                                                                                                                               
 (1.0, 8.0)                                                                                                                                                              
 (1.0, 8.0)                                                                                                                                                              

julia> [round.(x) for x in b]                                                                                                                                            
2-element Array{Tuple{Float64,Float64},1}:                                                                                                                               
 (1.0, 8.0)                                                                                                                                                              
 (1.0, 8.0)                                                                                                                                                              

```

---

<div class="post-metadata">

**Author:** ![favba](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/favba/32/2735_2.png) [@favba](https://discourse.julialang.org/u/favba)\
**Post date:** [October 31, 2017, 9:26pm UTC](https://discourse.julialang.org/t/elementwise-operation-on-array-of-tuples/6812/3 "2017-10-31T21:26:03Z")

</div>

A variant that still uses broadcast would be:

```julia
julia> (x->round.(x)).(b)
2-element Array{Tuple{Float64,Float64},1}:
 (1.0, 8.0)
 (1.0, 8.0)

```

* * *

I thought `round.(identity.(b))` would work, but it seems the `identity` function doesn’t broadcast?!

```julia
julia> identity(b)
2-element Array{Tuple{Float64,Float64},1}:
 (1.23457, 7.65432)
 (1.23457, 7.65432)

julia> identity.(b)
2-element Array{Tuple{Float64,Float64},1}:
 (1.23457, 7.65432)
 (1.23457, 7.65432)

julia> round.(identity.(b))
ERROR: MethodError: no method matching round(::Tuple{Float64,Float64})
Closest candidates are:
  round(::Type{BigInt}, ::BigFloat) at mpfr.jl:221
  round(::Float64) at float.jl:352
  round(::Float32) at float.jl:353
  ...

```

Is that a bug or expected behaviour?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 31, 2017, 9:33pm UTC](https://discourse.julialang.org/t/elementwise-operation-on-array-of-tuples/6812/4 "2017-10-31T21:33:59Z")

</div>

That’s just `broadcast(x->round(identity(x)), b)` so it’s totally expected.

---

<div class="post-metadata">

**Author:** ![BenjaminBorn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/benjaminborn/32/4910_2.png) [@BenjaminBorn](https://discourse.julialang.org/u/BenjaminBorn)\
**Post date:** [November 1, 2017, 9:00am UTC](https://discourse.julialang.org/t/elementwise-operation-on-array-of-tuples/6812/5 "2017-11-01T09:00:03Z")

</div>

Thanks for all the answers. Comparing two of the options

```julia
function mapround(b)
	map(x -> round.(x), b)
end

function nomapround(b)
	(x -> round.(x)).(b)
end

a = (1.234567,7.654321)
b = [a; a; a; a; a; a; a;]

@time mapround(b)
@time nomapround(b)

0.000002 seconds (6 allocations: 368 bytes)
0.000002 seconds (5 allocations: 352 bytes)

```

So it seems the second option saves me one allocation. Do I understand it correctly that the second option would also allow for loop fusion in larger dot expressions while `map` would not?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 1, 2017, 9:15am UTC](https://discourse.julialang.org/t/elementwise-operation-on-array-of-tuples/6812/6 "2017-11-01T09:15:37Z")

</div>

You are conflating compilation time and runtime. Benchmark using `BenchmarkTools`:

```julia
using Compat # workaround for an issue
using BenchmarkTools

mapround(b) = map(x -> round.(x), b)

nomapround(b) = (x -> round.(x)).(b)

a = (1.234567,7.654321)
b = fill(a, 7)

@benchmark mapround($b)
@benchmark nomapround($b)

```

gives

```julia
julia> @benchmark mapround($b)
BenchmarkTools.Trial: 
  memory estimate: 208 bytes
  allocs estimate: 2
  --------------
  minimum time: 63.930 ns (0.00% GC)
  median time: 66.071 ns (0.00% GC)
  mean time: 74.597 ns (7.00% GC)
  maximum time: 1.177 μs (84.75% GC)
  --------------
  samples: 10000
  evals/sample: 982

julia> @benchmark nomapround($b)
BenchmarkTools.Trial: 
  memory estimate: 192 bytes
  allocs estimate: 1
  --------------
  minimum time: 53.977 ns (0.00% GC)
  median time: 56.167 ns (0.00% GC)
  mean time: 62.408 ns (5.13% GC)
  maximum time: 736.473 ns (82.53% GC)
  --------------
  samples: 10000
  evals/sample: 986

```

`@code_warntype` tells you that the second one inlines. Frankly, I would not worry about the difference.

---

<div class="post-metadata">

**Author:** ![BenjaminBorn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/benjaminborn/32/4910_2.png) [@BenjaminBorn](https://discourse.julialang.org/u/BenjaminBorn)\
**Post date:** [November 1, 2017, 9:29am UTC](https://discourse.julialang.org/t/elementwise-operation-on-array-of-tuples/6812/7 "2017-11-01T09:29:24Z")

</div>

Thanks Tamas. That‘s interesting. Just a quick follow up. I ran the @time lines multiple times, so why am I conflating compile and runtime?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 1, 2017, 9:32am UTC](https://discourse.julialang.org/t/elementwise-operation-on-array-of-tuples/6812/8 "2017-11-01T09:32:20Z")

</div>

Sorry, I was not aware that you ran `@time` multiple times (it is a good thing to do, but your code did not indicate this). If you did, you were indeed not measuring compilation. But you still get benchmarking noise.

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [November 4, 2017, 9:50am UTC](https://discourse.julialang.org/t/elementwise-operation-on-array-of-tuples/6812/9 "2017-11-04T09:50:32Z")

</div>

I think using `map` is more iodiomatic, and I agree the difference in performance shouldn’t matter here.
