2016-11-10 76 views
2

我有一個數組:用Ruby中的第一個字母搜索數組?

dictionary = [ 
    'abnormal', 
    'arm-wrestling', 
    'absolute', 
    'airplane', 
    'airport', 
    'amazing', 
    'apple', 
    'ball' 
] 

如何搜索前五場比賽,或者如果沒有五場比賽更少,通過他們的第一個字母?

input = "a" 
match = dictionary.select { |a| a.match(input) } 
puts match 

match回報

["abnormal", "arm-wrestling", "absolute", "airplane", "airport", "amazing", "apple", "ball"] 

,但我需要它返回

["abnormal", "arm-wrestling", "absolute", "airplane", "airport"] 

,不返回的話就像["ball"]只是因爲它包含 「A」。

+0

您的字典已經排序? – Stefan

+0

字典應該保持原樣。它不能改變。它應該按字典中給出的順序返回所有結果,即使它們並不總是按字母順序排列。 –

+1

我不想改變你的數組,但是_if_你的數組是排序的,你可以使用'bsearch_index'來查找第一個單詞的索引而不是遍歷整個數組。 – Stefan

回答

7

如果我理解正確,您需要以'a'開頭的前五個單詞。

您可以使用String#start_with?

dictionary.select { |word| word.start_with?('a') }.first(5) 

爲了獲得更好的性能,您可以選擇lazy這五個字。該計劃將特別意義,如果你是在執行搜索的集合越來越大:

dictionary.lazy.select { |word| word.start_with?('a') }.first(5) 

對於不區分大小寫的選擇:

dictionary.lazy.select { |word| word.start_with?('a', 'A') }.first(5) 
+1

您可以在'.select'之前添加一個'.lazy',以便在找到5個匹配項後停止遍歷數組。 – Stefan

+0

@AndreyDeineko這是一個非常準確的答案,謝謝。 –

+0

@AndreyDeineko我可以搜索不區分大小寫嗎?例如,單詞「你好」以「h」字母開頭,但它沒有找到這個單詞,因爲第一個「你好」字母是空格。 –

3
▶ dictionary.group_by { |w| w[0] } 
#⇒ { 
# "a" => [ 
#  [0] "abnormal", 
#  [1] "arm-wrestling", 
#  [2] "absolute", 
#  [3] "airplane", 
#  [4] "airport", 
#  [5] "amazing", 
#  [6] "apple" 
# ], 
# "b" => [ 
#  [0] "ball" 
# ] 
# } 

dictionary.group_by { |w| w[0] }['a'].take(5)將返回所要求的陣列。

,或者使用grep

dictionary.grep(/\Aa/).take(5) 

,或者偷懶:

dictionary.lazy.grep(/\Aa/).first(5) 
+0

我認爲OP查找以「a」開頭的前5個詞(至少這是我怎麼理解的?我怎樣才能通過第一個字母搜索前5個匹配?) –

+0

@AndreyDeineko啊,的確,thx。 – mudasobwa

1

貌似有很多答案被扔掉了,沒有考慮到處理速度。這並不試圖測量返回第一五個字,只有確定是否單詞開始的'a'

words = %w[ 
    aback 
    agonizing 
    bell 
    bubble 
    dear 
    lackadaisical 
    mouth 
    nonstop 
    rinse 
    steel 
    stroke 
] 

var = 'a' 

require 'fruity' 

與此相比,所有:

var = 'a' 
compare do 
    starts_with { words.select { |w| w.start_with?('a') } } 
    downcase { words.select { |w| w.downcase.start_with?('a') } } 
    regexp { words.select { |w| w[0] =~ /a/i } } 
    mudasobwa1 { words.select { |a| %w|a A|.include? a[0] } } 
    mudasobwa2 { words.group_by { |w| w[0] }['a'] } 
    mudasobwa3 { words.grep(/\Aa/).to_a } 
    mudasobwa4 { words.lazy.grep(/\Aa/).to_a } 
    stefan { words.select { |word| word.start_with?('a', 'A') } } 
    andrey_deinko { words.select { |a| a[0] =~ /#{var}/ }} 
    andrey_deinko2 { words.lazy.select { |word| word.start_with?('a') }.to_a } 
end 

# >> Running each test 2048 times. Test will take about 4 seconds. 
# >> starts_with is similar to stefan 
# >> stefan is similar to downcase 
# >> downcase is faster than mudasobwa1 by 2x ± 0.1 
# >> mudasobwa1 is similar to mudasobwa3 
# >> mudasobwa3 is similar to regexp 
# >> regexp is similar to mudasobwa2 
# >> mudasobwa2 is similar to andrey_deinko2 
# >> andrey_deinko2 is similar to mudasobwa4 
# >> mudasobwa4 is faster than andrey_deinko by 4x ± 1.0 

要盡力幫助lazy方法,我擴大所述words數組的大小由1000:

words = (%w[ 
    aback 
    agonizing 
    bell 
    bubble 
    dear 
    lackadaisical 
    mouth 
    nonstop 
    rinse 
    steel 
    stroke 
] * 1000).shuffle 

重新運行節目:

# >> Running each test 2 times. Test will take about 4 seconds. 
# >> starts_with is similar to stefan 
# >> stefan is similar to andrey_deinko2 
# >> andrey_deinko2 is similar to downcase 
# >> downcase is similar to mudasobwa2 
# >> mudasobwa2 is similar to mudasobwa1 
# >> mudasobwa1 is similar to mudasobwa3 
# >> mudasobwa3 is similar to mudasobwa4 
# >> mudasobwa4 is similar to regexp 
# >> regexp is faster than andrey_deinko by 9x ± 1.0 

有一個嚴重的速度與正則表達式支付所以學習使用錨點。我不會在這裏討論它,但是有關於顯示差異的問題和答案,以便搜索它們。

保持簡單。利用爲此設計的內置方法。

+1

「懶惰」方法(至少在這種情況下)的意義在於,當您從大型列表中拉出前幾項時,它們會提高性能。如果沒有'lazy','select'就會處理整個列表,當它真的可能在五點之後停止時。但是如果你忽略'我只想要前五'的要求,那麼'懶惰'當然不會添加任何東西。 – philomory

相關問題