Ruby 分享一段 ruby 代码,真是美如画啊

scuwolf · 2013年08月28日 · 最后由 Victor 回复于 2013年09月21日 · 3579 次阅读

这么一段代码涉及了很多 ruby 的知识点。

尤其是在 initialize 中直接接受 block 参数太漂亮了,想想如果要实现不同的排序方法,只需要将这个方法生成一个 Proc,传递给数组就可以了。

class SortedArray < Array

  def initialize(*args,&sort_by)
    @sort_by = sort_by || Proc.new { |x,y| x <=> y }
    super(*args)
    sort! &@sort_by
  end

  def insert(i,v)
    insert_before = index(find {|x| @sort_by.call(x,v) == 1})
    super(insert_before ? insert_before : -1, v)
  end

  def <<(v)
    insert(0,v)
  end

  alias push <<
  alias unshift <<

  ["collect!","flatten!","[]="].each do |method|
    self.class_eval %{
      def #{method}(*args)
        super
        sort! &@sort_by
      end
    }
  end
end

这个效率很差啊,每次都要重新 sort,Array 还有很多口子没处理 concat 啊,delete_if 啊等等。先 find 遍历,再用 index 效率也很低,不在乎重复元素直接用 SortedSet 还好点。

内置的 sort 方法是用 C 实现的吧?

............

这段代码怎么美如画了?感觉纯粹是掉书袋,涉及到的知识点倒确实不少

讲下嘛,涉及了哪些知识点

#5 楼 @fsword

创作如绘画,在能表达主题的基础之上,还讲究一笔就勾出神韵,画面减无可减,当中没有任何多余的东西。简洁,而不简陋。

代码的简洁,是在不影响阅读的基础上,用最简单直接的方式实现,每一句话,每一个字符都是必须的(这个角度看,ruby 中不应该用括号)。《代码整洁之道》和《编写可读代码的艺术》关于这方面都有很系统的总结。

这段代码真的很简洁,变量的取名也不错,应该优化了好几个版本吧!大家读下来都知道作用是什么,而且能一口气读完。

除了简洁之外,美的代码还会注意排版的美观,很在意对齐,我觉得这段代码还可以更美的。

忍不住用我的理解的方式改了一下:

class SortedArray < Array

  def initialize( *args, &sort_by )
    @sort_by = sort_by || Proc.new { |x,y| x <=> y }
    super *args
    sort_self!
  end

  def insert( i, v )
    next_neighbour  = find { |x| @sort_by.call(x,v) > 0 }
    insert_before   = index( next_neighbour ) || -1
    super insert_before, v
  end

  def <<( v )
    insert 0, v
  end

  alias push    <<
  alias unshift <<

  # 其实加入concat这样的入口非常方便,在这个数组里面添加就是了
  methods_to_wrap = %w[
    collect!
    flatten!
    []=
    concat
  ]

  methods_to_wrap.each do |method|
    # 这里我尝试用 define_method 代替 class_eval
    # 这样阅读代码的时候,能有更好的语法高亮。
    # 但是 define_method 不支持 *args 这样的动态
    # 参数,只好放弃了。保持 class_eval
    class_eval %{
      def #{method}(*args)
        super
        sort_self!
      end
    }
  end

  private

    # 加入这个private method 是为了DRY,很多地方都用到了
    def sort_self!
      sort! &@sort_by
    end

end

至于性能优化,是另外的话题,至少 insert 方法有优化空间

:)

def <<( v ) 可以改成 def << v

#7 楼 @sevk 嗯,是的,不过 def 这一行我还是习惯加括号,感觉方法名会更清晰一点 << 这个方法确实没有括号更好!

草草草草草看不懂

完全看不懂,看来 Python 还是要适合我一些...

#10 楼 @ted block , proc, class_eval 而已, 怎么会看不懂呢?

到底懂不懂什么是美?代码跟美有毛关系?

#12 楼 @Victor 妞跟美有毛关系?

#13 楼 @liwei78 这真的有关。

#14 楼 @Victor 妞 =~ /美/ 美.match(/妞/)

#15 楼 @liwei78 不懂。好像你的代码不能运行哦。

#16 楼 @Victor 美在一个妞身上排第几?是个妞就美么??

#17 楼 @liwei78 你这是啥奇怪问题啊。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号