映射一个数组,仅修改符合特定条件的元素
在 Ruby 中,以修改某些元素而其他元素保持不变的方式映射数组的最具表现力的方法是什么?
这是一种直接的方法:
old_a = ["a", "b", "c"] # ["a", "b", "c"]
new_a = old_a.map { |x| (x=="b" ? x+"!" : x) } # ["a", "b!", "c"]
如果还不够的话,当然可以省略“leave-alone”情况:
new_a = old_a.map { |x| x+"!" if x=="b" } # [nil, "b!", nil]
我想要的是这样的:
new_a = old_a.map_modifying_only_elements_where (Proc.new {|x| x == "b"})
do |y|
y + "!"
end
# ["a", "b!", "c"]
在 Ruby 中是否有一些好的方法可以做到这一点(或者也许 Rails 有一些我还没有找到一种方便的方法)?
谢谢大家的回复。 虽然你们集体说服我最好只使用 map
和三元运算符,但你们中的一些人发布了非常有趣的答案!
In Ruby, what is the most expressive way to map an array in such a way that certain elements are modified and the others left untouched?
This is a straight-forward way to do it:
old_a = ["a", "b", "c"] # ["a", "b", "c"]
new_a = old_a.map { |x| (x=="b" ? x+"!" : x) } # ["a", "b!", "c"]
Omitting the "leave-alone" case of course if not enough:
new_a = old_a.map { |x| x+"!" if x=="b" } # [nil, "b!", nil]
What I would like is something like this:
new_a = old_a.map_modifying_only_elements_where (Proc.new {|x| x == "b"})
do |y|
y + "!"
end
# ["a", "b!", "c"]
Is there some nice way to do this in Ruby (or maybe Rails has some kind of convenience method that I haven't found yet)?
Thanks everybody for replying. While you collectively convinced me that it's best to just use map
with the ternary operator, some of you posted very interesting answers!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
因为数组是指针,所以这也有效:
在循环中,确保使用更改对象的方法而不是创建新对象。 例如,
upcase!
与upcase
相比。确切的过程取决于您到底想要实现什么目标。 很难通过 foo-bar 的例子给出明确的答案。
Because arrays are pointers, this also works:
In the loop, make sure you use a method that alters the object rather than creating a new object. E.g.
upcase!
compared toupcase
.The exact procedure depends on what exactly you are trying to achieve. It's hard to nail a definite answer with foo-bar examples.
给出
map!
修改接收器,因此old_a
现在是返回的数组。gives
map!
modifies the receiver in place, soold_a
is now that returned array.我同意地图声明本身就很好。 简单明了,而且很容易
供任何人维护。
如果你想要更复杂的东西,这个怎么样?
I agree that the map statement is good as it is. It's clear and simple,, and would easy
for anyone to maintain.
If you want something more complex, how about this?
您的
map
解决方案是最好的。 我不知道为什么你认为 map_modifying_only_elements_where 更好。 使用map
更干净、更简洁,并且不需要多个块。Your
map
solution is the best one. I'm not sure why you think map_modifying_only_elements_where is somehow better. Usingmap
is cleaner, more concise, and doesn't require multiple blocks.一行:
在上面的代码中,您以 []“cumulative”开始。 当您通过枚举器进行枚举时(在我们的例子中为数组 ["a", "b", "c"]),累积项以及“当前”项被传递到我们的块(|cumulative, i|)并且我们的块的执行结果被分配给累积。 我上面所做的是当项目不是“b”时保持累积不变并附加“b!” 到累积数组并在为 b 时返回它。
上面有一个使用
select
的答案,这是执行(并记住)它的最简单方法。您可以将
select
与map
结合起来,以实现您正在寻找的内容:在
select
块内,您可以指定元素的条件被“选中”。 这将返回一个数组。 您可以在结果数组上调用“map”以将感叹号附加到它。One liner:
In the code above, you start with [] "cumulative". As you enumerate through an Enumerator (in our case the array, ["a", "b", "c"]), cumulative as well as "the current" item get passed to our block (|cumulative, i|) and the result of our block's execution is assigned to cumulative. What I do above is keep cumulative unchanged when the item isn't "b" and append "b!" to cumulative array and return it when it is a b.
There is an answer above that uses
select
, which is the easiest way to do (and remember) it.You can combine
select
withmap
in order to achieve what you're looking for:Inside the
select
block, you specify the conditions for an element to be "selected". This will return an array. You can call "map" on the resulting array to append the exclamation mark to it.Ruby 2.7+
从 2.7 开始就有了明确的答案。
Ruby 2.7 为此引入了
filter_map
。 这是惯用且高效的,我希望它很快就会成为常态。例如:
这是一个很好的读物主题。
希望这对某人有用!
Ruby 2.7+
As of 2.7 there's a definitive answer.
Ruby 2.7 is introducing
filter_map
for this exact purpose. It's idiomatic and performant, and I'd expect it to become the norm very soon.For example:
Here's a good read on the subject.
Hope that's useful to someone!
如果你不需要旧的数组,我更喜欢地图! 在这种情况下,因为您可以使用 ! 方法来表示您正在就地更改数组。
我更喜欢这个而不是:
If you don't need the old array, I prefer map! in this case because you can use the ! method to represent you are changing the array in place.
I prefer this over:
它有几行长,但这里有一个替代方案:
在我看来,带有三元的收集似乎是最好的。
It's a few lines long, but here's an alternative for the hell of it:
The collect with ternary seems best in my opinion.
我发现实现此目的的最佳方法是使用
tap
I've found that the best way to accomplish this is by using
tap