【问题标题】:Difference in output with map and each [duplicate]输出与地图的差异和每个[重复]
【发布时间】:2023-04-04 03:39:01
【问题描述】:

我需要帮助找出为什么 map 和以下代码中的 each 之间存在差异。

j = "This is an awesome string"

j.split('').map do |char|
    char.next! if char =~ /[A-Za-z]/
end

这会返回:

["U", "i", "j", "t", nil, "j", "t", nil, "b", "o", nil, "b", "x", "f", "t", "p", "n", "f", nil, "t", "u", "s", "j", "o", "h"]

但是

j.split('').each do |char|
    char.next! if char =~ /[A-Za-z]/

返回:

["U", "i", "j", "t", " ", "j", "t", " ", "b", "o", " ", "b", "x", "f", "t", "p", "n", "f", " ", "t", "u", "s", "j", "o", "h"]

为什么从map 更改为each 会去掉nil?

【问题讨论】:

  • 和往常一样,在 ruby​​ 中有一个单行符:"This is an awesome string".gsub(/[A-z]/) { |c| c.next } 与问题不严格相关,但仍然值得了解(我认为,无论如何)。
  • @asQuirreL 在你的路上.."This is an awesome string".enum_for(:gsub, /[a-z]/i).map(&:next) ...希望你会喜欢。它实际上是#map,它将在迭代期间向您展示它所做的事情。 :-)
  • 同样,有This is an awesome string".gsub(/[A-z]/, &:next)(您的解决方案的问题是它实际上删除了非字母字符,而不是忽略它们)。
  • @asQuirreL 这是#gsub .. 不是#gsub! ..别担心。 :-)

标签: ruby map each


【解决方案1】:

因为Array#each 返回接收器 本身。但是Array#mapmaps,每个当前字符,你传递给块,带有当前的计算结果。

对于#map,条件if char =~ /[A-Za-z]/ 被评估为falsy,对于每个传递的元素,如" "。因此,块映射nil,同时找到" "if 条件评估为falsy 的任何元素。但是#each在每次迭代完成后忘记了块结果,但是#map没有。

如果查看输出,您可以看到所有nil(s) 都在" " 的相同位置。这一观察也决定了我刚才提到的行为。

在 Ruby 中,每个代码块,例如类的定义、方法定义、块定义,都会返回它的最后一条语句。在您的#map 块中,if modifier 之后没有语句,因此它重新运行nil

在 Ruby >= 2.1.1 中,我看到了将其名称作为符号返回的方法。但是当你调用它时,它会返回它的最后一条语句。如果方法体为空,则为nil

往下看:-

[1] pry(main)> def foo
[1] pry(main)* end  
=> :foo
[2] pry(main)> foo
=> nil
[3] pry(main)> def baz
[3] pry(main)*   12
[3] pry(main)* end  
=> :baz
[4] pry(main)> baz
=> 12

更新

@asquirrel的评论中,我有了一个想法。你可以用更 Ruby 的方式编写代码:-

"This is an awesome string".gsub(/[a-z]/i).map(&:next)
# => ["U", "i", "j", "t", "j", "t", "b", "o", "b", 
# "x", "f", "t", "p", "n", "f", "t", "u", "s", "j", "o", "h"]

更新1

j = "This is an awesome string"

array = j.split('').map do |char|
  char =~ /[A-Za-z]/ ? char.next : char
end

p array 

# >> ["U", "i", "j", "t", " ", "j", "t", " ", "b", "o", " ", "b", 
# "x", "f", "t", "p", "n", "f", " ", "t", "u", "s", "j", "o", "h"]

【讨论】:

  • 如果我不希望它替换空格而是忽略并留下它怎么办?
  • @user2801122 查看更新。
  • 所以我的更新阻止了新代码保持干净的一行?
  • @user2801122 使用{ ..}将其写在一行中,它将变成一行.. :-) 删除do..end/
猜你喜欢
  • 1970-01-01
  • 2014-05-07
  • 1970-01-01
  • 1970-01-01
  • 2014-01-03
  • 2016-01-05
  • 2014-03-15
  • 2015-03-26
  • 2018-08-12
相关资源
最近更新 更多