Home > database >  Filter Array For IDs Existing in Another Array with Ruby on Rails/Mongo
Filter Array For IDs Existing in Another Array with Ruby on Rails/Mongo

Time:06-25

I need to compare the 2 arrays declared here to return records that exist only in the filtered_apps array. I am using the contents of previous_apps array to see if an ID in the record exists in filtered_apps array. I will be outputting the results to a CSV and displaying records that exist in both arrays to the console.

My question is this: How do I get the records that only exist in filtered_apps? Easiest for me would be to put those unique records into a new array to work with on the csv.

start_date = Date.parse("2022-02-05")
end_date   = Date.parse("2022-05-17")
valid_year = start_date.year
dupe_apps = []
uniq_apps = []

# Finding applications that meet my criteria:
filtered_apps = FinancialAssistance::Application.where(
    :is_requesting_info_in_mail => true, 
    :aasm_state => "determined",
    :submitted_at => {
        "$exists" => true, 
        "$gte" => start_date, 
        "$lte" => end_date })

# Finding applications that I want to compare against filtered_apps
previous_apps = FinancialAssistance::Application.where(
    is_requesting_info_in_mail: true,
    :submitted_at => {
        "$exists" => true, 
        "$gte" => valid_year })

# I'm using this to pull the ID that I'm using for comparison just to make the comparison lighter by only storing the family_id
previous_apps.each do |y|    
    previous_apps_array << y.family_id
end

# This is where I'm doing my comparison and it is not working.
filtered_apps.each do |app|
    if app.family_id.in?(previous_apps_array) == false
                then @non_dupe_apps << app
            else "No duplicate found for application #{app.hbx_id}"
            end
        end
    end

So what am I doing wrong in the last code section?

CodePudding user response:

Let's check your original method first (I fixed the indentation to make it clearer). There's quite a few issues with it:

filtered_apps.each do |app|
    if app.family_id.in?(previous_apps_array) == false
        # Where is "@non_dupe_apps" declared? It isn't anywhere in your example...
        # Also, "then" is not necessary unless you want a one-line if-statement
        then @non_dupe_apps << app

    # This doesn't do anything, it's just a string
    # You need to use "p" or "puts" to output something to the console
    # Note that the "else" is also only triggered when duplicates WERE found...
    else "No duplicate found for application #{app.hbx_id}"
        end # Extra "end" here, this will mess things up
    end
end

Also, you haven't declared previous_apps_array anywhere in your example, you just start adding to it out of nowhere.

Getting the difference between 2 arrays is dead easy in Ruby: just use -!

uniq_apps = filtered_apps - previous_apps

You can also do this with ActiveRecord results, since they are just arrays of ActiveRecord objects. However, this doesn't help if you specifically need to compare results using the family_id column.

TIP: Getting an array including only a specific column/columns from an ActiveRecord query is probably best done with the pluck method if you don't need to store any other data about those objects, since it happens on the database query level. You only get an array of values in the result, not the full objects.

# Querying straight from the database
# This is what I would recommend, but it doesn't print the values of duplicate records
uniq_apps = filtered_apps.where.not(family_id: previous_apps.pluck(:family_id))

I highly recommend familiarizing yourself with at least filter, map and possibly reduce out of the basic array methods. They make things like this way easier. A very simple example of doing a similar thing to what you explained in your question with filter on 2 arrays would be something like this:

arr = [1, 2, 3]
full_arr = [1, 2, 3, 4, 5]

unique_numbers = full_arr.filter do |num|
    if arr.include? num
        puts "Duplicates were found for #{num}"
        false
    else
        true
    end
end

# Duplicates were found for 1
# Duplicates were found for 2
# Duplicates were found for 3
=> [4, 5]
  • Related