问题
I am new to ruby and I wonder how you would indent this code:
if a.any? do |blah|
name = blah[:name][/.* (.*)/, 1]
name = convert_name(name)
text = "#{name}#{blah[:value]}"
text == "b2"
end
puts "found"
exit 1
end
回答1:
I'd write it something like:
if a.any? { |blah| (blah[:name] + blah[:value]) == "b2" }
puts "found"
exit 1
end
Or:
if a.any? { |blah| blah.values_at(:name, :value).join == "b2" }
puts "found"
exit 1
end
The actual test is short enough that it can be done in a single line.
Generally we use braces ({}
) for blocks when they return a value or are on a single line.
Interpolating two strings in another string just to join them is smelly. Just concatenate them; It's more obvious what you're doing.
If you're ONLY concerned about how to indent clearly, consider this:
if a.any? do |blah|
name = blah[:name][/.* (.*)/, 1]
name = convert_name(name)
text = "#{name}#{blah[:value]}"
text == "b2"
end
puts "found"
exit 1
end
The any?
block should be indented further than the contents of the if
block to visually separate them. Beyond the indention... ugh... the code block for any?
should be refactored to a single line still.
回答2:
Like so:
if(a.any? { |blah| text = "#{blah[:name]}#{blah[:value]}"; text == "b2"})
puts "found"
exit 1
end
If your any?
block is really long, do this:
result = a.any? do |blah|
text = "#{blah[:name]}#{blah[:value]}"
text == "b2"
...
end
if(result)
puts "found"
exit 1
end
回答3:
I'd probably toss the search logic into a lambda:
are_wanted = lambda do |blah|
name = blah[:name][/.* (.*)/, 1]
name = convert_name(name)
text = "#{name}#{blah[:value]}"
text == "b2"
end
Then once it has a name so that we can tell what it is for at a glance, the if
becomes nice and readable:
if a.any?(&are_wanted)
puts "found"
exit 1
end
I find this technique quite useful when you end up with a complicated Enumerable pipeline, things like this for example:
pull_em_apart = lambda { ... }
the_good_ones = lambda { ... }
put_em_back_together = lambda { ... }
array.map(&pull_em_apart)
.select(&the_good_ones)
.map(&put_em_back_together)
when the lambda
s are more than a single line are a lot easier to understand than a big mess of inlined blocks.
回答4:
Part of the challenge is to cleanly accommodate both the if
and any?
blocks, since both terminate with an end
. One way to distinguish between them, then, is to use braces for the inner block, to make it clearer what is going on:
if a.any? { |blah|
name = blah[:name][/.* (.*)/, 1]
name = convert_name(name)
text = "#{name}#{blah[:value]}"
text == "b2" }
then
puts "found"
exit 1
end
Thanks Cary Swoveland for suggesting the then
.
回答5:
Another choice:
begin
puts "found"
exit 1
end if a.any? do |blah|
name = blah[:name][/.* (.*)/, 1]
name = convert_name(name)
text = "#{name}#{blah[:value]}"
text == "b2"
end
来源:https://stackoverflow.com/questions/21193057/how-to-indent-if-any-do-end-end