2010-09-23 3 views
4

Итак, у меня есть массив, который выглядит так.Как удалить нежелательные из массива?

["Enter Sandman", "One", "Nothing Else Matters", "Master of Puppets", "The Unforgiven", "The Day That Never Comes", "For Whom the Bell Tolls", "Fade to Black", "Sad But True", "Wherever I May Roam", "Turn the Page", "I Disappear", "Fuel", "Cyanide", "Seek & Destroy", "Whiskey In the Jar", "All Nightmare Long", "Battery", "Welcome Home (Sanitarium)", "The Unforgiven III", "The Unforgiven II", "King Nothing", "Ride the Lightning", "No Leaf Clover", "Until It Sleeps", "...And Justice for All", "Blackened", "The Memory Remains", "Hero of the Day", "The Four Horsemen", "Orion", "Creeping Death", "St. Anger", "Harvester of Sorrow", "Don't Tread on Me", "Broken, Beat & Scarred", "Disposable Heroes", "Fight Fire With Fire", "The End of the Line", "Trapped Under Ice", "Of Wolf and Man", "Whiplash", "My Apocalypse", "Suicide & Redemption", "The Shortest Straw", "Tuesday's Gone"] 

Этот массив создается с помощью этой команды

artists = search_object.map{|x| x["trackName"]}.uniq.delete_if {|x| x == nil} 

это работает хорошо, но мне нужно, чтобы отфильтровать некоторые дополнительные элементы. Пользователь вводит текстовое поле, и по мере ввода мне нужно сузить результаты. Например, если пользователь набирает строку «Вопросы», мне нужно вынуть элементы, которые не имеют этого имени или имени. Таким образом, он раскрывается до «Nothing Else Matters». Если пользователь вводит букву «a», тогда все остальные в массиве, которые не имеют «a», удаляются.

они придут с Params [: текст]

Я сделал это, и она работала, но, возможно, есть более чистый способ

query = params[:term] 
artists = search_object.map{|x| x["trackName"]}.uniq.delete_if {|x| x == nil} 
filtered = [] 
artists.each do |artist| 
    filtered << artist if artist.include?(query) 
end 
+0

metallica_tracks << «Жить, чтобы умереть» – johnmcaliley

+3

Как Замечание, вы можете использовать 'compact' вместо' delete_if {| x | x == nil} '. – vonconrad

ответ

6

быстрый вариант рубин:

albums = ["hello kitty", "bad day", "all is good", "day is okay"] 

def filter_word_in(word,array) 
    array.delete_if { |data| !data.match(word) } 
    return array 
end 

result1 = filter_word_in("y", albums) 
puts result1.inspect # => ["hello kitty", "bad day", "day is okay"] 

result2 = filter_word_in("ay", result1) 
puts result2.inspect # => ["bad day", "day is okay"] 

result3 = filter_word_in("day", result2) 
puts result3.inspect # => ["bad day", "day is okay"] 

result4 = filter_word_in("day i",result3) 
puts result4.inspect # => ["day is okay"] 

Как вы можете видеть в этом коде: мы просто сохраняем наш результат в переменных. Итак, где мы можем хранить наши данные в рельсах? Вы можете использовать user_model для этого или просто сохранить эти данные в памяти.

Создать что-то вроде этого:

class UserSongMemory 
    attr_accessor :memory 

    def initialize 
     @memory = [] 
    end 

    def push(id, data) 
     @memory << {id => data} 
    end 

    def pop(id) 
     @memory.delete_if {|obj| obj.id == id} 
    end 
end 

user_memory = UserSongMemory.new 
user_memory.add(@user.id, params[:inputed_string]) 

# after our calculations 
user.pop(@user.id) 

Я предпочитаю хранить состояние памяти в классе, но не забудьте очистить этот класс-данные

+0

В зависимости от того, что вы хотите разрешить пользователям, вы также можете избежать символов регулярных выражений из 'data.match (word)'. В противном случае они могут вводить регулярные выражения для фильтрации результатов. – vonconrad

+0

Я согласен с вами. Я просто хочу показать способ, как это сделать. Где много вариантов поиска контента - регулярное выражение, сопоставление слов или, может быть, что-то вроде command-t%) – vorobey

1

Я хотел бы сделать это:

term, fname = params[:term], "trackName" 
filtered = search_object.map {|x| x[fname] if x[fname].match(term) }.compact.uniq 

Этот подход устраняет необходимость в двух петлях, один для сбора и другого выбора. Методы uniq и compact соответствуют вашим требованиям.

0

Класс Array предлагает вам метод «reject» для удаления нежелательных элементов из вашего массива.

0

Вот несколько иной подход и мои рассуждения.

Причина:
Я себе список на веб-странице с текстового поля, что позволяет вводить подстроку нужного выбора для фильтрации вниз к этому пункту. Таким образом, мое предположение заключается в том, что ваши пользователи будут ТОЛЬКО когда-либо печатать подстроку. Это не опытные пользователи, которые будут соответствовать регулярному выражению для желаемого трека. Просто используя select и include?, вы можете ограничить эту силу регулярного выражения, как предложили люди, без дополнительной сложности. Regex немного напоминает использование пулемета, чтобы убить муху в этом примере.

Код:
#I renamed the array, since it was a list of songs, not artists
songs.select {|s| s.upcase.include?(query.upcase)}
Вы можете оставить upcase, если вы хотите, чтобы запрос, чтобы быть чувствительны к регистру