One of the reasons I like writing in Ruby so much is because it is very capable of achieving a lot via one liners.
I like:
@sentence = @sentence.split(' ').map!{|x| x = x[0..0].upcase << x[1..-1] }.join(' ')
It capitalizes the first letter of each word, which is not the most stunning, but quite efficient.
What's the most elegant one liner you have seen or written with Ruby?
You posted the oneliner:
@sentence = @sentence.split(' ').map!{|x| x = x[0..0].upcase << x[1..-1] }.join(' ')
But you misunderstand a couple things about Ruby.
First off, saying x=
in a map call doesn't affect anything outside of the map call. The new value of that array element is the value returned by the block.
Secondly, you don't need to mutate the first string with <<
-- a concatenation that creates a new string (using +
) is a much better option.
Thirdly, map!
makes changes directly to the array returned by split
. What you want to do is leave that array untouched (even though it doesn't change program semantics), and return a new array with the mapped results, by using map
.
So you should have written:
@sentence = @sentence.split(' ').map{|x| x[0..0].upcase + x[1..-1] }.join(' ')
Now the statement x[0..0].upcase + x[1..-1]
is still very obtuse. Maybe you should replace it with the capitalize
method, which already changes the first letter of the string to uppercase. (Note that it also downcases all of the others, which may or may not be what you want.)
@sentence = @sentence.split(' ').map{|x| x.capitalize }.join(' ')
I'd probably use gsub!
to change parts of the string in-place, but that's probably a little obtuse:
@sentence.gsub!(/\S+/){|x| x.capitalize}
One more thing. If the only purpose of a block is to call a single method on the object passed to the block, you can do the following:
@sentence = @sentence.split(' ').map(&:capitalize).join(' ')
or to modify my gsub!
version:
@sentence.gsub!(/\S+/,&:capitalize)
You might want to take a look at Ruby Quiz #113.
Open a file, write to it, and close it in one line:
File.open(File.join(Rails.root, 'lib', 'assets', 'file.txt'), 'a+') {|f| f.write("stuff"+"\n" }
Most of my best Ruby one-liners in every day scripts utilize and
, unless
, if
, &&
and so forth, like:
puts "x is nil!" if x.nil?
You can use unless
and if
interchangeably, but unless
significantly improves readability when used correctly:
puts "bad input type!" unless ["bs", "cf", "is"].include?(type)
Oftentimes, the best Ruby one-liners are ultimately done in two to three lines of one-liners working together, often in conjunction with Ruby's "valence" system for variables (nil
and false
are the only "negatives"):
def try_first(actual_index)
x = [get_header(actual_index, 0), get_data(actual_index, 0)] unless get_header(actual_index, 0).blank?
x = try_second(actual_index) if x[0].blank? #blank is a rails method, detects nil and empty strings and empty containers ([]) I think too
puts "x is nil!" if x.nil?
x
end
I say one-liners composed of several one-liners because that method itself is less than a one-liner somewhere else in my code. Many of my methods just one line though:
def get_all_coords(type)
eval("@#{type}_coords")
end
That's how you really start to get elegant. Break out code into individual methods. One-line methods are perfect.
The Fibonacci number for sure!
def fib(n, t = n < 2 ? n : fib(n-1) + fib(n-2)) t; end
Well, I wrote one a few days ago but couldn't use it as an answer because the question was closed by then. It replaces the first line of a file with a string if the string isn't already there.
I hope someone improves on this one also:
ruby -i.bak -pe "print ($_!~/string/ && $.<2) ? \"string\n\":''" filename.txt
Fibonacci sequence generator:
def fib n;n==0?[0]:n==1?[0,1]:(2..n-1).inject([0,1]){|a|a<<(a[-1]+a[-2])};end
same as:
def fib n;n<2?(0..n-1).to_a():(2..n-1).inject([0,1]){|a|a<<(a[-1]+a[-2])};end
Absolutely this emulation of GREP (Windows user). [credit goes to Dave Thomas]
ruby -pe 'next unless $_ =~ /regexp/' < file.txt
精彩评论