Reputation: 5495
I have the following structure in Julia and I create an array with it.
julia> struct myStruct
a::Int
b::Int
c::String
end
julia> myArray = myStruct.(1:10,11:20,"ABC")
10-element Array{myStruct,1}:
myStruct(1, 11, "ABC")
myStruct(2, 12, "ABC")
myStruct(3, 13, "ABC")
myStruct(4, 14, "ABC")
myStruct(5, 15, "ABC")
myStruct(6, 16, "ABC")
myStruct(7, 17, "ABC")
myStruct(8, 18, "ABC")
myStruct(9, 19, "ABC")
myStruct(10, 20, "ABC")
What shall I do in Julia to get the maximum value of a
?
Is it recommended to first getting a 2 column array with the first two values of the struct and then use findmax(my2colArray[:,1])
to find the maximum value?
I have three questions to understand how shall I do this:
a
directly from the array of structs?Upvotes: 1
Views: 922
Reputation: 12654
The easiest way to get the max value of a
is, as @fredrikekre writes:
maxval = maximum(x->x.a, arr)
Unfortunately, this does not give you the index of that value, which you also asked for in a comment.
Ideally, you could use argmax
or findmax
instead:
(maxval, maxind) = findmax(x->x.a, arr) # <= This does not work!!
Currently, at version 1.2 of Julia, this does not work.
There may be some other clever solution, but my advice is to just write a loop yourself, it's easy and educational!
To address your questions:
0: (This was not a question) Remember to always name your types with UpperCamelCase: so MyStruct
, not myStruct
.
No, you don't need this, and it's not a good solution. (Also I don't know why you want a 2-column vector, when you only are looking for the max of a
). But if you really want it anyway:
v = getproperty.(x, [:a :b])
For max value, see the answer by @fredrikekre, for max index see below.
No, I don't think so.
Write your own loop to get the max index and value. It's easy and fun, and you learn to write your own fast Julia code:
function find_amax(arr::AbstractArray{MyStruct})
isempty(arr) && ArgumentError("reducing over an empty collection is not allowed")
maxind, maxval = firstindex(arr), first(arr).a
for (i, x) in enumerate(arr)
if x.a > maxval
maxind, maxval = i, x.a
end
end
return maxval, maxind
end
There is a small inefficiency in the code above, the first value and index of x
is read twice. If you want even faster performance, you can figure out a way to avoid that.
As for performance, this loop is about as fast as maximum(x->x.a, arr)
, and more than 60x as fast as building the 2-column matrix you asked for in question 1.
The main lesson is: You don't need to look for some clever "built-in" solution that you can plug your problem into. If you cannot quickly find one, just make your own, it will most likely be faster.
Upvotes: 2
Reputation: 10984
You can use the maximum
function. maximum
also takes a function, which you, in this case, can use to sort by the a
field:
julia> struct myStruct
a::Int
b::Int
c::String
end
julia> myArray = myStruct.(21:30,11:20,"ABC");
julia> val = maximum(x -> x.a, myArray)
30
(Slightly modified your example to make the maximum value and the index different).
Upvotes: 4