nathaks nathaks - 6 months ago 14
Ruby Question

How to remove duplicates in an array of arrays ruby

I'm doing a flight booker application on Rails and have successfully listed dates of flights as arrays but I have a problem with duplicates.

I'm doing a select_tag(:dates, options_for_select(@dates)

It works but I've got all these duplicate dates.

Heres the code for @dates.

@dates=Flight.all.map do |a|
dates=[]
unless dates.any? && dates.last[0]==a.flight_date_formatted
dates<<[a.flight_date_formatted, a.id]
end
end


This returns an array of arrays of the type of ["22/5/2016", 1] I can't use unique because of the second element, the id is always different.

In the code I'm trying to access the last/first element of the array and get its [0] element, which would be "22/5/2016" and if it's equal to the current date then skip this iteration. Unfortunately it doesn't work.

There are 7 flights and only 3 different Dates so it's not hard for it to catch at least one different.

Answer

To query the flights directly from the database uniquely by date and already sorted, you can use ActiveRecord do this:

today = DateTime.now.to_date
@flights = Flight.select("DISTINCT flight_date, *").where("flight_date < ?", today).group(:flight_date).order("flight_date")

In this, the DISTINCT and group are used to make the flights unique by flight_date. The order is used to sort the results; if you wanted them sorted in reverse order, use order("flight_date DESC"). The where says to only retrieve the flights that have a flight date before today. Any of these can be changed to suit similar queries, as well.

If have already retrieved duplicates from the database, you can sort them in memory with the Ruby standard library Array#unique with a block. Try this:

@flights = Flight.all.unique {|a,b| a[0] <=> b[0] }

This will return an array that is unique by the first element.

To correct your filter code, you just need to return the dates value from the block. This should return the correct value from the map block:

@dates=Flight.all.map do |a|
  dates=[]
  unless dates.any? && dates.last[0]==a.flight_date_formatted
    dates<<[a.flight_date_formatted, a.id]
  end
  dates
end

The "short" way to filter out records is with Array#select, which you can use like this:

today = DateTime.now.strftime("%-d/%-m/%Y")
@flights = @flights.select {|flight| flight[0] != today }