我有一个字符串数组maxlen = stringarr.max_by(&:size).size
,并想知道最长字符串的长度。我对字符串本身不感兴趣。
我的第一个解决方案是
maxlen = stringarr.map(&:size).max
工作,但很丑:我不得不提两次大小,这很容易出错,并且最长字符串的大小需要计算两次。好吧,字符串没什么大不了的,但请参见下文。
另一个想法是
maxlen = stringarr.inject(0) {|memo,s| [memo.size,s.size].max}
从可读性的角度来看清洁,但需要创建一个临时数组。也不好。
这是另一次尝试:
maxlen = stringarr.max_of(&:size) # Sadly no max_of in Ruby core
也不完美......
我想知道是否有更好的方法。我的愿望就像是
maxlen = measurement(stringarr.max_by {|s| measurement(s)})
当我有一个更复杂的代码块时,这将特别令人感兴趣。这当然不是好风格:
{{1}}
有什么建议吗?
答案 0 :(得分:3)
我认为你的inject
方法可能是最干净的,但它有一个错误。您记住大小,然后在记忆号码上拨打.size
。
请改为尝试:
maxlen = stringarr.inject(0) {|memo,s| [memo,s.size].max}
答案 1 :(得分:1)
偷走编译@msergeant和@sebastián-palma:
require 'benchmark'
N = 10_000
stringarr = Array.new( N, 'Lorem Ipsum dolor sit amet' )
Benchmark.bm do |x|
x.report { stringarr.map(&:size).max }
x.report { stringarr.max_by(&:size).size }
x.report { stringarr.sort_by(&:size)[-1].size }
x.report { stringarr.inject(0) { |memo,s| [memo,s.size].max } }
x.report { stringarr.inject(0) { |memo,s| memo > s.size ? memo : s.size } }
end
我的赢家是@ msergeant使用三元运算符的变体,当裸[memo,s.size].max
是最慢的时候。您可以在环境中使用其他stringarr
数据获得不同的结果。
答案 2 :(得分:0)
根据我收到的答案和评论,我决定为此目的向Enumerable
添加方法。我在这里发帖,以防有人想从中受益,或者相反批评它:
class Enumerable
# Similar to map(&block).max, but more efficient
#
# x.max_of {|s| f(s)} returns the largest value f(s), or nil if x is empty.
# x(seed).max_of {|s| f(s)} returns the largest value f(s), provided that it
# is larger than seed, or returns seed, if no such
# element exists or x is empty.
def max_of(seed = nil)
enumerator = each
result = nil
begin
if seed
result = seed
else
result = yield(enumerator.next)
end
loop do
next_val = yield(enumerator.next)
result = next_val if next_val > result
end
rescue StopIteration
end
result
end
end