0

I have a list of car makes

 makes = [acura, honda, ford]

and I'm trying to iterate through an array of strings and find out if the individual string contains one of these makes AND if it does, to put that specific makes into an array

so I've got

strings.each do |string|

  if string.include?(*makes)

  else

  end
end

how do I use the current argument of the splat process to determine which make matched up with the string? Is there a way to do this?

Edit: As I posted in the comments below, I'm looking for a specific make to be returned, instead of a true/false answer. So if the string is "New toyota celica", the return should be "toyota".

falsetru
  • 357,413
  • 63
  • 732
  • 636
Kwestion
  • 464
  • 5
  • 19

3 Answers3

3

Using Enumerable#any?:

makes = ['acura', 'honda', 'ford']
strings = ['hyundai acura ford', 'sports car']

strings.each do |string|
  p makes.any? { |make| string.include? make }
end

Alternative that use regular expression: (See Regexp::union)

strings = ['hyundai acura ford', 'sports car']
makes = ['acura', 'honda', 'ford']
pattern = Regexp.union(makes)

strings.each do |string|
  p string.match(pattern) != nil
end

UPDATE

strings.each do |string|
  p makes.find { |make| string.include? make }
end

or

strings.each do |string|
  p makes.select { |make| string.include? make }
end
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • Using `String#join` here is ugly. You should use `Regexp.union`. – sawa Nov 02 '13 at 12:39
  • 1
    @sawa, Thank you for your advice. I updated the answer according to your comment. – falsetru Nov 02 '13 at 12:41
  • Interesting, question that still is open - is escaping necessary. – Edgars Jekabsons Nov 02 '13 at 12:44
  • @sawa, According to [`Regexp` documentation](http://www.ruby-doc.org/core-2.0/Regexp.html), it is denoted as `::union`. Actually both `Regexp::union` and `Regexp.union` are acceptable. – falsetru Nov 02 '13 at 12:47
  • Not going much in to the offtopic, but on interpreter level both notations work the same, though I agree with @sawa about avoiding `::`. – Edgars Jekabsons Nov 02 '13 at 12:48
  • 1
    @EdgarsJekabsons, `Regexp::union` escapes the strings. For example, `Regexp.union(['a.b', '^$'])` yields `/a\.b|\^\$/`. – falsetru Nov 02 '13 at 12:49
  • @falsetru Sorry, my comment about `::` did not make sense. I removed it. And good point about automatic escape. – sawa Nov 02 '13 at 13:03
  • just ran this in ruby fiddle, these return a true or false. I'm looking for the specific make in the string. So if the string is "New toyota celica" I would check against the makes array and it would return "toyota" instead of "true". Let me know if I misunderstood your answer! I can be a bit dense sometimes. – Kwestion Nov 02 '13 at 20:01
  • @Kwestion, Then, try `strings.each do |string| p makes.select { |make| string.include? make } end` or `strings.each do |string| p makes.find { |make| string.include? make } end` – falsetru Nov 02 '13 at 20:05
  • WORKS! Thanks for answering so quick, really helpful for a ruby n00b like me. – Kwestion Nov 02 '13 at 20:10
1

If Your makes are not very long, then one of the shortest thing would be using Regex, as already suggested:

makes = ['acura', 'honda', 'ford']
strings = ['hyundai acura ford', 'sports car']
strings.grep(/#{makes.join('|')}/)

 # => ["hyundai acura ford"]

After a slight discussion we came up this to be one of the best choices:

strings.grep(Regexp.union(makes))
Edgars Jekabsons
  • 2,833
  • 15
  • 20
0

Another way, by intersecting arrays:

makes = ["acura", "honda", "ford"]

strings = [
"I own a Toyota and a Ford",
"My friend Becky loves her Acura",
"I plan to buy a BMW",
"I now have an Acura, but have had both a honda and a Ford"
]

strings.each do |s|
  a = s.scan(/(\w+)/).flatten.map(&:downcase) & makes
  puts "#{s}\n" + (a.empty? ? "  No matches" : "  Matches: #{a.join}")
end

I own a Toyota and a Ford
  Matches: ford
My friend Becky loves her Acura
  Matches: acura
I plan to buy a BMW
  No matches
I now have an Acura, but have had both a honda and a Ford
  Matches: acura honda ford

Note that it is necessary to use scan with a regex, rather than split, as punctuation would be a problem with the latter (e.g., 'Acura,` would not be matched).

Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100