# Arrays to vector conversion

Hello all,

I am trying to write a function where i have to compare two quantities, the simplified representation of the problem where i am stuck is as

I get these type of two quantities as follows:

``````a = [[9], [8]]
b = [9.0121, 9.008]

if isapprox(a, b; atol=1e-5)
print ("done")
else
print("not done")
end
``````

I am not able to compare “a” and “b” and it is giving me this error ` DimensionMismatch: dimensions must match: a has dims (Base.OneTo(0),), b has dims (Base.OneTo(2),), mismatch at 1`

I guess i have to convert “b” such that its shape is similar to “a”, any idea how can i do that? thank you

You could use: `reduce(vcat,a)`, to convert `a` to a vector like `b`, which seems simpler than the other way around.

2 Likes

If I run your code I don’t get a `DimensionMismatch` error. Instead I get `ERROR: MethodError: no method matching -(::Vector{Int64}, ::Float64)`.

It’s not just a problem of different shapes, but of very different types. Note that `[[9], [8]]` In Julia is not a matrix with two rows like in Numpy. It’s a vector that contains two vectors. If that’s really what you want, and if you know that all the vectors in `a` have one element, you can do `isapprox(only.(a), b; atol=1e-5)`. Here `only.(a)` will collect the single elements of `[9]` and `[8]` into a new vector `[9, 8]`.

1 Like

Something like

``````all(isapprox(x, y, tol) for (x, y) in zip(flatten(a), flatten(b))))
``````

`flatten` is from `Iterators`, and is the key. It will unroll nested arrays to any depth, spitting out scalars, without allocating intermediate arrays.

Warning: untested and written on a phone.

A merge of @sijo and @DNF solutions, that is short and non-allocating:

``````all(isapprox(only(x), y; atol=1e-5) for (x,y) in zip(a,b))
``````

However, these non-allocating approaches do not seem to do exactly the same as OP, because for vector inputs a vector norm is used.

1 Like

Using `isapprox` elementwise is often a bad idea. For example:

``````julia> isapprox([1, 0], [1, 1e-16])
true

julia> all(isapprox.([1, 0], [1, 1e-16]))
false
``````

`1e-16 ≈ 0` is false, and rightly so, because the two numbers have no significant digits in common, and there is no reference by which to set an absolute scale. (You don’t know the “units”. See also the `isapprox` documentation on why the default tolerance is relative error, not absolute error.)

The advantage of applying `isapprox` to the whole array at once is that the norm of the whole array sets an overall scale with which to compare the elements: `1e-16 - 0` is small compared to the norm `≈ 1`, so `[1,0] ≈ [1,1e-16]` rightly returns `true`.

Approximate comparison is one of those things that’s really easy to get wrong, unfortunately. (e.g. `numpy.isclose` got it wrong.)

PS. I think “non-allocating” here is probably an irrelevant metric. `isapprox` is not something that you usually do in performance-critical settings.

4 Likes