Ruby:获取最长字符串的长度

时间:2017-06-09 14:49:20

标签: ruby

我有一个字符串数组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}}

有什么建议吗?

3 个答案:

答案 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