Help me understand unintuitive behavior of array comparison

julia> minimum([[1,1e10,1e10],[2,0,0]])
3-element Array{Float64,1}:
 1.0
 1.0e10
 1.0e10

I would expect this to return either the same as min.() or a MethodError, but instead only the first elements are compared. Similarly [1,1e10,1e10]<[2,0,0] is true, there is probably a good reason why but it’s hard to google for it.

it’s comparing element by element (pair from both arrays) until it finds two elements that are not the same, and it will compare those two:

"""
    isless(A::AbstractVector, B::AbstractVector)

Returns true when `A` is less than `B` in lexicographic order.
"""
isless(A::AbstractVector, B::AbstractVector) = cmp(A, B) < 0

2 Likes

Thanks for the answer. I guess I understand what it does, but not quite sure about the why. Is this standard in other languages? I can think of at least two other equally plausible ways to determine this comparison:

  • which array’s sum is larger
  • which array is larger in most element-wise comparisons

It is in python, at least.

I think that is the why.

The option makes mostly sense for strings, arrays of characters, such things, which is how we organize things in dictionaries:

julia> [ 'B', 'A' ] < [ 'C' ]
true

julia> [ 'B', 'A' ] < [ 'A' ]
false

julia> "ba" < "c"
true

julia> "ba" < "a"
false


1 Like

Just for fun, I tried a few. Here’s Python:

>>> min([1,1e10,1e10], [2,0,0])
[1, 10000000000.0, 10000000000.0]

and Ruby:

irb(main):001:0> [[1,1e10,1e10], [2,0,0]].min
=> [1, 10000000000.0, 10000000000.0]

and C++:

julia> using Cxx

C++ > std::vector<std::vector<double>> values = {{1,1e10,1e10}, {2,0,0}}
true

C++ > auto min = *std::min_element(values.begin(), values.end())
true

C++ > min[0]
(double &) 1.0

C++ > min[1]
(double &) 1.0e10

C++ > min[2]
(double &) 1.0e10

These all agree with Julia because they’re all doing the same basic thing: comparing each vector in the list lexicographically.

6 Likes

Yes. It’s called lexicographic order.

2 Likes

Alright, thank you everyone for the responses! I never think about strings. Interesting that R is then the exception, as it does element-wise comparison by default, returning a boolean vector.

This is because R has basically no concept of scalars, just vectors of unitary length. Consequently, element-wise operations are the default. Julia goes on the opposite direction, with a general broadcast operator that does element-wise operations when requested, so the default of every operation can be the non-element-wise interpretation (to be broadcasted on demand by just adding a single dot).

3 Likes

Pretty much, but not may not be the relevant question. The important thing is that it is documented, see ?isless.