Home > database >  How to filterout the arrays from aray of an array based on an attribute in ruby?
How to filterout the arrays from aray of an array based on an attribute in ruby?

Time:03-10

I have an array that has some extra information along with the ids and i want to use this ids to filter out arrays from an array of array. Below is an example.

[[#<Position:0x00007fc32a124b80
   self_id: 1077,
   position_id: 5,
   person_id: 57,
   started_on: Thu, 01 Sep 2016,
   ended_on: nil,
   branch_id: 45,
   relevant_position: true],
[#<Position:0x00007fc32a1652c0
   self_id: 1732,
   position_id: 8,
   person_id: 3219156,
   started_on: Mon, 01 Feb 2021,
   ended_on: nil,
   branch_id: 45,
   relevant_position: true]]

so, I want to use 'person_id'(57 and 3219156) present in the above array to be used to filter out the array given below

[#<Person:0x00007fc32909a058
   id: 57,
   nationality_id: 2,
   title_id: 1,
   company_id: 44974,
   gender_id: 3,
   marital_status_id: 4,
   partner_id: nil>,
#<Person:0x00007fc329098488
  id: 3219156,
  nationality_id: 1,
  title_id: 1,
  company_id: 44974,
  gender_id: 3,
  marital_status_id: 1,
  partner_id: nil>,
#<Person:0x00007fc329098488
 id: 3106438,
 nationality_id: 1,
 title_id: 1,
 company_id: 44974,
 gender_id: 3,
 marital_status_id: 1,
 partner_id: nil>]

In the second array we have array with 'ids' so I want those arrays to be filtered out where 'person_id' from first array is not present in the 'id' of that element in second array. In this case last element of second array should be filtered out as its 'id' is not present in first array's 'person_id'.

CodePudding user response:

There are of course better ways to do this kind of thing with Rails or any database, but you seem to be asking for a pure-Ruby approach, so here are some options for that.

Option 1:

filtered_array = people_array.filter do |person|
    positions_array.find{|pos| pos.person_id == person.id}
end.to_a

#filter will return an array with only elements that return a 'truthy' value from the block. Since #find will either return the person element itself (considered 'truthy') if it matches the criteria or nil (not considered 'truty') if the element is not found this satisfies the block and filters as you intend.

Note the #to_a after the block. #filter returns and enumerator, not an array so you need to convert it. Of course you can just use the enumerator in its lazy form instead of building an array if that suits you.

Option 2:

people_ids = positions_array.map(&:person_id).sort.uniq

filtered_array = people_array.filter do |person|
    people_ids.include?(person.id)
end.to_a

Here we build an array of people's ids from the positions and sort and remove duplicates with #uniq before filtering the people array by calling Array#include? to see if the person's id is present in the array of ids we want.

This option may perform better in some scenarios.

Also, about the positions_array.map(&:person_id) line. If you haven't seen that syntax before it's just shorthand for this: positions_array.map{|pos| pos.person_id }.

Again, do this only if you are intent on not using Rails or a database. But hopefully there are some Ruby lessons in here that might be valuable elsewhere.

CodePudding user response:

If you are using Rails, you can learn about associations to handle stuff like this. See a tutorial here: https://guides.rubyonrails.org/association_basics.html

  • Related