Как сопоставить строку в массиве, независимо от размера строки в Ruby - PullRequest
0 голосов
/ 24 февраля 2020

Я пытаюсь выяснить следующее:

Когда я запускаю это в терминале, используя Ruby, строка в массиве удаляется, пока это не будет сделано, когда я продолжу вводить строку, которая является в массиве saxophone_section. Но я все еще хочу иметь возможность удалить строку из массива, когда я набираю «альт-саксофон 1» и потому что «альт-1» находится во входной строке.

Как я могу это сделать, когда строка в массиве совпадений независимо от размера входной строки?

saxophone_section = ["alto 1", "alto 2", "tenor 1", "tenor 2", "bari sax"]

until saxophone_section == []

puts "Think of sax parts in a jazz big band."
print ">>"

sax_part = gets.chomp.downcase


# this is the part that is confusing me.  Trying to figure out the method in which 
# a string in the above array matches an input, whether "alto 1" or "alto saxophone 1" 
# or "Eb alto saxophone 1" is typed in ("alto 1" is found in all).  
# How can I make it true in all three (or more) cases?

saxophone_section.any?(sax_part)

# I am thinking that this bottom parts one could be used? or not?
parts = saxophone_section.map {|sax| sax.gsub(/\s+/m, ' ').strip.split(" ")}


#this is the loop to delete the item in the array:

if saxophone_section.include?(sax_part) == true

p saxophone_section.delete_if{ |s| s == sax_part}
puts "Damn, you're lucky"
else
  puts "Woops! Try again."
end
end
puts "You got all parts."

Ответы [ 3 ]

0 голосов
/ 24 февраля 2020

Вы должны использовать регулярное выражение, чтобы соответствовать вводу. Таким образом, вместо создания массива строк, попробуйте массив регулярных выражений, например, так:

saxophone_section = [/alto\s(?:.*\s)?1/, /alto\s(?:.*\s)?2/, /tenor\s(?:.*\s)?1/, /tenor\s(?:.*\s)?2/, /bari\s(?:.*\s)?sax/]

Затем используйте сопоставление со всеми элементами в массиве по отношению к вводу, чтобы найти совпадение с вводом string;

sax_part = gets.chomp.downcase

index = saxophone_section.find_index { |regex| sax_part.match(regex) }

Позже вы можете использовать этот индекс для удаления элемента из массива, если он не равен nil;

saxophone_section.delete(index)

Или вы можете просто использовать метод Array#delete_if для удаления элемента непосредственно из массива, например так:

saxophone_section.delete_if { |regex| sax_part.match(regex) }

Примечание: Вы можете использовать https://www.rubular.com для проверки ваших регулярных выражений.

0 голосов
/ 25 февраля 2020

Вот где я бы начал с такого рода задач; Это отличные строительные блоки для человеческих интерфейсов в Интернете или в приложениях:

require 'regexp_trie'

saxophone_section = ["alto 1", "alto 2", "tenor 1", "tenor 2", "bari sax"]
RegexpTrie.union saxophone_section   # => /(?:alto\ [12]|tenor\ [12]|bari\ sax)/

Вывод RegexpTrie.union - это шаблон, который будет соответствовать всем строкам в saxophone_section. Шаблон является лаконичным и эффективным, и, что лучше всего, его не нужно генерировать вручную.

Применение этого шаблона к создаваемой строке покажет, есть ли у вас попадание при совпадении, но только когда строки достаточно для совпадения.

Вот где обычный Tr ie очень полезен. Когда вы пытаетесь найти возможные удары, которые вы могли бы получить, до полного матча Tr ie может найти все возможности:

require 'trie'

trie = Trie.new
saxophone_section = ["alto 1", "alto 2", "tenor 1", "tenor 2", "bari sax"]

saxophone_section.each { |w| trie.add(w) }
trie.children('a') # => ["alto 1", "alto 2"]
trie.children('alto') # => ["alto 1", "alto 2"]
trie.children('alto 2') # => ["alto 2"]
trie.children('bari') # => ["bari sax"]

Смешайте их вместе и посмотрите, что вы придумали с.

0 голосов
/ 24 февраля 2020

Преобразование строк в массив и выполнение операции пересечения должны быть опцией. Я знаю, это не лучшее решение, но может спасти ваш день.

[17] pry(main)> x = "alto saxophone 1"
=> "alto saxophone 1"
[18] pry(main)> y = "i am not an anglophone"
=> "i am not an anglophone"
[19] pry(main)> z = "alto 1"
=> "alto 1"
[20] pry(main)> x.split & z.split == z.split # & is array intersection
=> true
[21] pry(main)> x.split & y.split == y.split
=> false
...