Sorting a list of maps by date

payload = [
  %{
    company_id: 1,
    updated_at: ~U[2020-01-01 11:56:41.882841Z],
    name: "Garland",
    state: :pending,
    user_count: 3
  },
  %{
    company_id: 2,
    updated_at: ~U[2020-01-01 11:56:48.308506Z],
    name: "Garland",
    state: :started,
    user_count: 3
  },
  %{
    company_id: 3,
    updated_at: ~U[2020-01-01 06:04:00.279130Z],
    name: "Garland",
    state: :done,
    user_count: 3
  }
]

I am attempting to sort a list of 3-4 maps by date. This is what I have tried so far with no luck:

data
|> Enum.sort_by(fn each ->
  d = each.updated_at
  {d.year, d.month, d.day}
end)

Alternatively, how can I sort by state? Essentially I want to grab the step it is on (e.g completed if it exists, or started if that’s the latest one, or pending if that’s the latest one. )

Something like this maybe:

Enum.sort(payload,fn a, b ->
  case DateTime.compare(a.updated_at, b.updated_at) do
    :gt -> false
    _ -> true
  end
end)

It will be easier to sort by dates in Elixir 1.10
https://github.com/elixir-lang/elixir/blob/master/CHANGELOG.md#improvements-to-sort-based-apis-in-enum

4 Likes

ah, problem is that your entries are all on the same date. if you want to sort on datetime, probably you want this:

Enum.sort(payload, &(DateTime.compare(&1.updated_at, &2.updated_at) != :gt))

to sort on state AND datetime, note that the documentation says that it’s stable if two equivalent values are equal, so you can do:

payload
|> Enum.sort(&(sort_states/2))
|> Enum.sort(&(DateTime... --as above--)

You can sort by multiple properties with Enum.sort_by/3. There’s an example in the docs.

2 Likes