The Crystal Programming Language Forum

How to sort an Array of NamedTuples?

I have an Array of NamedTuples I’m trying to sort:

post_images : Array({slug: String, filename: String}) = Array({slug: String, filename: String}).new

# << items appended here

post_images.sort_by! { |i| i[:filename] } # This doesn't work

post_images.sort! { |a, b| a[:filename] <=> b[:filename] } # Neither does this

Here’s the error:

199 | v = v1 <=> v2
              ^--
Error: undefined method '<=>' for NamedTuple(slug: String, filename: String)

Am I missing something simple?

Incidentally, this was the first thing I tried:

post_images.sort_by! { |i| i.filename }
51 | post_images.sort_by! { |i| i.filename }
                                   ^-------
Error: undefined method 'filename' for NamedTuple(slug: String, filename: String)

post_images.sort_by! { |i| i[:filename] } works fine tho?

https://play.crystal-lang.org/#/r/8hbe

EDIT: Probably would be better to define a struct for this? Then you could include Comparable and define the <=> which would allow you to just call .sort on the array.

It’s weird that I’m getting that error. I changed your snippet to append << to see if that was my issue, but it works.

One difference I didn’t post was that my function’s return type is really nilable:

def post_banner_images(logger : ColorizedLogHandler, post : Post, size : (NamedTuple(width: Int32, height: Int32) | Nil) = nil) : Array({slug: String, filename: String})?
end

But the branch inside is guaranteed to be not null where I’m appending and trying to sort before returning. My only guess is the compiler doesn’t like that?

Probably would be better to define a struct for this? Then you could include Comparable and define the <=> which would allow you to just call .sort on the array.

Yeah, I do that exactly thing elsewhere in my code base where I’m defining a Post class and Author class. However, for this little post images I thought I just use a throw-away NamedTuple instead…

Can you make a playground link with an example where its not working?

I couldn’t, a simplified version of the function worked in the playground as well.

That lead me down the path of using --error-trace to get more details… It turned out that I forgot to delete another reference I had before moving the sort to the function. That other original attempt at sort was causing the problem.

Thanks for your help!

1 Like