2016-08-14 65 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