Delete array element if next elements value overrides previous element value

Hello! For example, I have array:

[["can", ":manage", ":site", nil], ["can", ":view", ":dashboard", nil], ["cannot", ":manage", ":site", nil]]

And I want to remove ["can", ":manage", ":site", nil] element, basing on that ":manage" and ":site" elements are equal, but "cannot" element appears later than "can". How can i achieve that?

Use the middle two elements as a hash key.

-Dave

Solved it like that:

abilities_array =     roles.map(&:abilities).flatten(1).each do |e|       if i = abilities_array.find_index{|ar| ar[1]==e[1] && ar[2]==e[2]}         abilities_array[i] = e       else         abilities_array << e       end     end     abilities_array.map{|a| "#{a[0]} #{a[1]}, #{a[2]}#{", "+a[3] unless a[3].blank?}"}

I'm not even going to try to grok how that works. Using a temporary hash as a filter is much simpler:

tmp_hash = {} roles.map(&:abilities).each do |ability|   tmp_hash[ability[1,2]] = ability end abilities_array = tmp_hash.values

Or with tap:

abilities_array = {}.tap { |tmp_hash|   roles.map(&:abilities).each do |ability|     tmp_hash[ability[1,2]] = ability   end }.values

(If you want *earlier* ones to take precedence, use ||= instead of =.)

Hashes are one of your bestest friends in the whole wide world. At least, the world of Ruby. :wink: They're very fast, and extremely useful.

-Dave

tmp_hash = {} roles.map(&:abilities).each do |ability|   tmp_hash[ability[1,2]] = ability end abilities_array = tmp_hash.values

Or with tap:

abilities_array = {}.tap { |tmp_hash|   roles.map(&:abilities).each do |ability|     tmp_hash[ability[1,2]] = ability   end }.values

Thank you, it looks much better =)