mateo_io
mateo_io

Reputation: 398

How to remove duplicates in an array of arrays Ruby

I'm doing a flight-booking application in Rails and have successfully listed dates of flights as arrays.

However, I have a problem with duplicates. I've used a select_tag(:dates, options_for_select(@dates), which 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, in which 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 isn't working as I expect.

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

How can I filter the duplicate records?

Upvotes: 1

Views: 489

Answers (1)

Michael Gaskill
Michael Gaskill

Reputation: 8042

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 }

Upvotes: 2

Related Questions