使用以下代码来选择字符串的每个其他字符并从中创建一个新字符串:
def bits(string)
string.chars.each_with_index.select {|m, index| m if index % 2 == 0}.join
end
但是,select使用测试用例“hello”返回此输出:
"h0l2o4"
使用地图时,我会得到所需的结果:
"hlo"
在这种情况下,选择不起作用的原因是什么?在什么情况下使用map而不是select更好?反之亦然
答案 0 :(得分:1)
如果您仍想使用select
,请尝试此操作。
irb(main):005:0> "hello".chars.select.with_index {|m, index| m if index % 2 == 0}.join
=> "hlo"
each_with_index
不起作用,因为它同时选择了字符和索引,然后加入所有这些。
答案 1 :(得分:0)
如果使用Enumerable#map,您将返回一个数组,该数组为字符串中的每个字符都有一个元素。
arr = "try this".each_char.map.with_index { |c,i| c if i.even? }
#=> ["t", nil, "y", nil, "t", nil, "i", nil]
与
相同nil
我的初步答案建议在加入之前使用Array#compact删除arr.compact.join
#=> "tyti"
:
compact
但正如@npn所说,nil's
不是必需的,因为Array#join将NilClass.to_s应用于arr.join
#=> "tyti"
,将它们转换为空字符串。你可以简单地写一下
map
您可以使用"try this".each_char.each_cons(2).map(&:first).join
#=> "tyti"
的另一种方法是首先应用Enumerable#each_cons来传递字符对,然后返回每对字符的第一个字符:
"try this".each_char.select.with_index { |c,i| i.even? }.join
#=> "tyti"
即便如此,Array#select更可取,因为它只返回感兴趣的字符:
even = [true, false].cycle
#=> #<Enumerator: [true, false]:cycle>
"try this".each_char.select { |c| even.next }.join
#=> "tyti"
其中一个变体是:
map
使用Array#cycle创建枚举器,使用Enumerator#next生成元素。
一件小事:String#each_char比String#chars的内存效率更高,因为前者返回枚举器而后者创建临时数组。
通常,当接收器是阵列时,
Array#select
。"Now is the time to have fun.".scan(/(.)./).join
#=> "Nwi h iet aefn"
或Array#reject(或Enumerable#select或Enumerable#reject。我,我会使用一个简单的正则表达式:
{{1}}
答案 2 :(得分:0)
select在这种情况下不起作用的原因是select“返回一个包含枚举的所有元素的数组,给定的块返回一个真值”(参见文档here),所以你得到了什么在你的情况下是一个数组数组[['h',0],['l',2],['o',4]]然后你加入来获得“h0l2o4”。
因此select返回可枚举的子集。 map返回所提供的可枚举的一对一映射。例如,以下内容将通过使用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
由于很多原因,这不是从字符串中获取所有其他字符的好方法。
这是使用map的另一个例子。在这种情况下,每个索引都映射到字符或nil然后连接。
def bits(string)
string.chars.each_index.map {|i| string[i] if i.even? }.join
end