1

I have a list of strings in an array like so...

playlist_track_names = ["I Might", "Me & You", "Day 1", "I Got You (feat. Nana Rogues)", "Feels So Good (feat. Anna of the North)", "306", "Location Unknown (feat. Georgia)", "Crying Over You (feat. BEKA)", "Shrink", "I Just Wanna Go Back", "Sometimes", "Forget Me Not"] 

Then I have an array of hashes like so...

[
  {"id"=>"1426036284", "type"=>"songs", "attributes"=>{"name"=>"I Might", "albumName"=>"Love Me / Love Me Not" },
  {"id"=>"1426036285", "type"=>"songs", "attributes"=>{"name"=>"Feels So Good (feat. Anna of the North)", "albumName"=>"Love Me / Love Me Not" },
  {"id"=>"1426036286", "type"=>"songs", "attributes"=>{"name"=>"Forget Me Not", "albumName"=>"Love Me / Love Me Not" },
  {"id"=>"1426036287", "type"=>"songs", "attributes"=>{"name"=>"Some Other Name", "albumName"=>"Love Me / Love Me Not" }
]

What I want to do is remove any item from the array of hashes where attributes['name'] matches any of the names in the playlist_track_names array.

How would I do that?

Shpigford
  • 24,748
  • 58
  • 163
  • 252
  • 2
    By the way, there are tens of thousands of questions on Stack Overflow about "how do I deal with this array of hashes of strings to strings" or something similar, and the answer is always the same: Ruby is an object-oriented language, not an array-of-hashes-from-strings-to-strings-oriented language. Re-design your data model so that you don't have those complex structures in the first place, and then you don't need to deal with them. – Jörg W Mittag Aug 29 '18 at 22:43
  • @JörgWMittag Agreed. This insane data model is from a third-party API that I have no control over. I'd love to not have to deal with this. :) – Shpigford Aug 30 '18 at 02:17
  • Then don't deal with it. Wrap it into your own data model. – Tom Lord Aug 30 '18 at 06:12
  • Here's a couple of examples of what @TomLord is talking about: https://stackoverflow.com/a/43033758/2988, https://stackoverflow.com/a/45847433/2988, https://stackoverflow.com/a/28051415/2988, https://stackoverflow.com/a/20612726/2988, https://stackoverflow.com/a/32502358/2988, https://stackoverflow.com/a/33125872/2988, https://stackoverflow.com/a/31388268/2988. – Jörg W Mittag Aug 30 '18 at 08:08

2 Answers2

2

It looks like your hash_list is missing some closing brackets. I've added them below. Try running this in irb:

playlist_track_names = ["I Might", "Me & You", "Day 1", "I Got You (feat. Nana Rogues)", "Feels So Good (feat. Anna of the North)", "306", "Location Unknown (feat. Georgia)", "Crying Over You (feat. BEKA)", "Shrink", "I Just Wanna Go Back", "Sometimes", "Forget Me Not"] 

hash_list = [
  {"id"=>"1426036284", "type"=>"songs", "attributes"=>{"name"=>"I Might", "albumName"=>"Love Me / Love Me Not" } },
  {"id"=>"1426036285", "type"=>"songs", "attributes"=>{"name"=>"Feels So Good (feat. Anna of the North)", "albumName"=>"Love Me / Love Me Not" } },
  {"id"=>"1426036286", "type"=>"songs", "attributes"=>{"name"=>"Forget Me Not", "albumName"=>"Love Me / Love Me Not" } },
  {"id"=>"1426036287", "type"=>"songs", "attributes"=>{"name"=>"Some Other Name", "albumName"=>"Love Me / Love Me Not" } }
]

hash_list.delete_if { |i| playlist_track_names.include? i["attributes"]["name"] }
puts hash_list
Joseph Cho
  • 4,033
  • 4
  • 26
  • 33
0

You can use Array#delete_if to delete any entries which match a block. In the block use Array#include? to check if the track name is in the list.

tracks.delete_if { |track|
  playlist_track_names.include? track["attributes"]["name"]
}

Note that because playlist_track_names.include? has to search through playlist_track_names one by one this will get slower as playlist_track_names gets larger. You can avoid this by using a Set.

require 'set'

playlist_track_names = ["I Might", "Me & You", ...].to_set

A Set is like a Hash with just keys, no values. They're an unordered collection of unique values which are very fast to lookup. playlist_track_names.include? on a Set will perform the same no matter how large playlist_track_names gets.

Schwern
  • 153,029
  • 25
  • 195
  • 336