Isapprox for array of tuples


#1

My aim is to approximately compare two arrays of tuples for needs of regression tests. There should be a more simple way to do isapprox(R,R2) than the following

    R = [
         (4.0, 75.96375653207353)
         (6.0, 79.81178239308181)
         (8.0, 81.19371107853809)
         (9.0, 83.6598082540901)
         (10.0, 81.8365732447175)
         (12.0, 85.04173693954638)
         (15.0, 85.6845991057258)
         (16.0, 86.42366562500266)
         (20.0, 87.06652779118207)
         (25.0, 87.70938995736148)
        ];
    R2 = [
          (4.0, 82.8749836510982)
          (6.0, 85.23635830927383)
          (8.0, 86.42366562500266)
          (9.0, 86.82016988013577)
          (10.0, 87.13759477388825)
          (12.0, 87.61405596961119)
          (15.0, 88.09084756700362)
          (16.0, 88.21008939175394)
          (20.0, 88.56790381583535)
          (25.0, 88.8542371618249)
         ];

@test all([ all(map( (i,j) -> isapprox(i,j), R[k], T[k])) for k in 1:length(first.(R)) ])

Thanks!


#2
all(all.(map((i,j) -> isapprox.(i,j), R, R2))) 

Broadcasting makes it a bit more concise, but I’ve always found handling nested data structures like this rather clunky.

Comprehension syntax might make it a bit less clunky seeming than map?

all(all.(isapprox.(i,j) for (i,j) in zip(R,R2)))

EDIT: Actually, using Base.Iterators does provide a clean solution:

using Base.Iterators

all(isapprox.(flatten(R), flatten(R2)))

#3

Note that you may or may not want elementwise isapprox: you might want to set the tolerance based on the norm of the whole array.

For example, do you want [(0.0,1.0)] to be approximately equal to [(1e-100,1.0)]? Your comparison will return false, because isapprox(0.0, 1e-100) is false: see the documentation on x ≈ 0. However, if you look at the whole array at once, the other entry 1.0 sets a scale against which 1e-100 can be viewed as “small”.

The alternative would be to look at the whole array at a time, e.g. via:

isapprox(collect(Iterators.flatten(R)), collect(Iterators.flatten(R2)))

or, even more simply:

isapprox(collect.(R), collect.(R2))