2016-08-14 85 views
0

有下面的代碼應該選擇一個字符串的所有其它字符,並作出新的字符串了出來:Ruby的選擇方法,選擇值不符合標準

def bits(string) 
    string.chars.each_with_index.select {|m, index| m if index % 2 == 0}.join 
end 

然而,select返回此與測試輸出案 「你好」:

"h0l2o4" 

當使用地圖,而不是我得到期望的結果:

"hlo" 

是否有選擇在這種情況下不起作用的原因?在什麼情況下最好使用map over select,反之亦然

回答

0

如果使用Enumerable#map,則會返回一個數組,其中每個字符在字符串中都有一個元素。

arr = "try this".each_char.map.with_index { |c,i| i.even? ? c : nil } 
    #=> ["t", nil, "y", nil, "t", nil, "i", nil] 

這是一樣的

arr = "try this".each_char.map.with_index { |c,i| c if i.even? } 
    #=> ["t", nil, "y", nil, "t", nil, "i", nil] 

我最初的答案使用Array#compact加盟之前刪除nil小號建議:

arr.compact.join 
    #=> "tyti" 

但@npn筆記,compact是沒有必要的因爲Array#joinNilClass.to_s應用於nil's,將它們轉換爲空字符串秒。人機工程學,你可以簡單地寫

arr.join 
    #=> "tyti" 

你可以使用map是先申請Enumerable#each_cons通過對字符,然後返回每對的第一個字符的另一種方式:

"try this".each_char.each_cons(2).map(&:first).join 
    #=> "tyti" 

即使如此,Array#select是優選的,因爲它返回只有感興趣的字符:

"try this".each_char.select.with_index { |c,i| i.even? }.join 
    #=> "tyti" 

這方面的一個變體是:

even = [true, false].cycle 
    #=> #<Enumerator: [true, false]:cycle> 
"try this".each_char.select { |c| even.next }.join 
    #=> "tyti" 

它使用Array#cycle創建枚舉和Enumerator#next以產生其元素。

一個小的事情:String#each_char是更多的內存效率比String#chars,因爲前者返回的枚舉,而後者產生一個臨時數組。

通常,當接收器是一個數組,

我,我會用一個簡單的正則表達式:

"Now is the time to have fun.".scan(/(.)./).join 
    #=> "Nwi h iet aefn" 
+0

我不認爲你真的不需要在加入之前調用compact來從數組中刪除nil。 #join,每個元素都有#to_s類,而NilClass有一個返回「」的to_s方法。所以我不認爲這是依靠無證行爲跳過.compact調用的情況。 – nPn

+0

@nPn,謝謝你的糾正。我編輯過。 –

1

如果你還是想用select,試試這個。

irb(main):005:0> "hello".chars.select.with_index {|m, index| m if index % 2 == 0}.join 
=> "hlo" 

each_with_index,因爲它是選擇無論在角色和索引,然後加入全部不起作用。

0

在這種情況下,select不起作用的原因是select「返回一個包含給定塊返回真值的enum的所有元素的數組」(參見文檔here),所以你會得到什麼是數組[['h',0],['l',2],['o',4]]的數組,然後您可以加入以獲得「h0l2o4」。

所以選擇返回一個可枚舉的子集。 map將返回提供的enumerable的一對一映射。例如,以下內容將通過使用map從select返回的每個值中提取字符來「解決」您的問題。

def bits(string) 
    string.chars.each_with_index.select {|m, index| m if index % 2 == 0}.map { |pair| pair.first }.join 
end 

puts(bits "hello") 
=> hlo 

由於很多原因,這不是從字符串中獲取其他任何字符的好方法。

這是另一個使用地圖的例子。在這種情況下,每個索引都映射到字符或零,然後加入。

def bits(string) 
    string.chars.each_index.map {|i| string[i] if i.even? }.join 
end