新手问题 大家来重构 Season 3

blacktulip · 2013年08月20日 · 最后由 qhwa 回复于 2013年08月20日 · 3143 次阅读

要过的测试:

https://gist.github.com/qingwang/5c33fbcfc0e58cd9bbc4

需求:

Write a program that, given a word and a list of possible anagrams, selects the correct one(s).

Given `"listen"` and `%w(enlists google inlets banana)` the program should return "inlets".

我的做法:

class Anagram

  def initialize(word)
    @word = word
  end

  def match(list)
    remove_identicals_in(list).select{ |item| anagram?(item) }
  end

  private
    attr_accessor :word

    def anagram?(other_word)
      sort_chars(word) == sort_chars(other_word)
    end

    def remove_identicals_in(list)
      list.reject{ |item| item.downcase == word.downcase }
    end

    def sort_chars(word)
      word.downcase.chars.sort
    end
end

求板砖,求毁三观...

require 'set'

class String
  def anagram?(other)
    other.split('').to_set == self.split('').to_set
  end
end

#1 楼 @pongyo to_set 不行吧,这样子 banbanana 就一样了

(self.chars - word.chars) == []

==========分割线========== 过 test code 一定要写个 class??

def anagram?(other_word)
  word.chars -- other_word.chars == []
end

Sorry 刚才贴错测试代码了... 现在改过来了

#3 楼 @quakewang 不行... 这样写的话 galea 能匹配 eagle ; listen 能匹配 enlists ..

2.0.0p247 :001 > 'galea'.chars - 'eagle'.chars
 => []
2.0.0p247 :002 > 'listen'.chars - 'enlists'.chars
 => []

楼主这么写挺好的啊,trivial 的问题就 trivial 的解决

#5 楼 @blacktulip 哦,刚刚看懂测试案例,这样应该能过:

class String
  def check_sum
    self.chars.inject(Hash.new(0)){|h, a| h[a.downcase] += 1; h}
  end
end

class Anagram
  def initialize(word)
    @word = word
  end

  def match(list)
    list.reject{ |l| l.check_sum != @word.check_sum }
  end
end

@quakewang Anagram = String 还能省几行...

#8 楼 @luikore String 有 match 方法,这样做真大丈夫么?

class String
  def check_sum
    self.chars.inject(Hash.new(0)){|h, a| h[a.downcase] += 1; h}
  end
end

class Anagram < String
  def match(list)
    list.reject{ |l| l.check_sum != self.check_sum }
  end
end

#7 楼 @quakewang 感谢,我总是想不到可以割开 String 这种东西放个 method 进去... 这个除了 corn CORN 的测试没过,别的都过了。

#10 楼 @blacktulip 那只能再加个 l.downcase == self.downcase 判断了

你的重构系列一般到最后,都变成了比代码少了,这真的很

话说为啥不在 new 的时候就把那个算好...

class Anagram < Struct.new(:word, :sorted_chars)
  def initialize w
    super w.downcase, w.downcase.chars.sort
  end

  def match list
    list.find_all do |e|
      a = Anagram.new e
      a.word != word and a.sorted_chars == sorted_chars
    end
  end
end

#11 楼 @quakewang 专门为了 比代码少 当然是不好的... 但是像我这样的新手看你们的代码能学到很多技巧啊,有些东西我完全想不到,看了才知道...

#9 楼 @quakewang TDD 为求通过测试不择手段... 还可以祭出终极手段把 assert 重定义必通过...

#12 楼 @luikore 好精简的代码,喜欢!

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