Ruby中的否定条件语句

时间:2016-10-21 18:43:17

标签: ruby syntax conditional

似乎RubyMine IDE在看到负面条件语句时发出警告。我想知道为什么使用否定条件语句是坏的?这纯粹是出于可读性吗?

例如,在此代码中:

class Complement
    def self.of_dna dna_strand
      dna_array =  dna_strand.chars
      dna_complement  = ['']
      dna_structure = ['C', 'G', 'T', 'A']

      dna_array.each do |strand|
        unless dna_structure.include? strand 
          return ''
        end

        case strand
        when "C"
         dna_complement << "G"
        when "G"
         dna_complement << "C"
        when "T"
         dna_complement << "A"
        when "A"
         dna_complement << "U"
        end
      end
    dna_complement.join('')
  end
end

我想知道在这种情况下unless dna_structure.include? strandif !(dna_strucutre.include?)之间有什么不同?

3 个答案:

答案 0 :(得分:6)

由于Ruby不仅仅是if,而是unless,因此只要结果代码清晰,就会鼓励您使用它。那就是你应该转换这样的东西:

if (!string.empty?)
  # ...
end

这样的事情:

unless (string.empty?)
  # ...
end

这有例外,比如你有这个:

if (!string.empty?)
  # ... when not empty
else
  # ... when empty (when not not empty)
end

天真的方法是将其转换为unless但会产生三重否定。你已经在这里处理了一个double,else子句仅在字符串不是为空时发生,或者说不包含任何

请改为:

if (string.empty?)
  # ... when empty
else
  # ... when not empty
end

你在这里采用的方法存在许多问题,但最严重的是你每次调用方法时都在方法中声明一个常量数组。因为从来没有改变使它成为班级顶层的常数。至少:

class Complement
  DNA_STRUCTURE = %w[ C G A T ]
end

更好的方法是使用映射表来表示配对:

COMPLEMENT = {
  'C' => 'G',
  'G' => 'C',
  'T' => 'A',
  'A' => 'U'
}.freeze

现在看看你试图“反转”给定字符串的特定问题,你真正想要的工具是tr字符串本身,这是一种针对像cyphers这样的事情进行优化的方法字符之间有1:1的映射。

你的整个功能都崩溃了:

def self.of_dna(strand)
  strand.tr('CGTA', 'GCAU')
end

现在,如果您想进行快速测试以确保实际处理有效序列:

def self.of_dna(strand)
  return '' unless (strand.match(/\A[CGTA]*\z/))

  strand.tr('CGTA', 'GCAU')
end

你还会遇到其他一些不良习惯,比如当字符串在特定任务中更好时,创建数组来保存单个字符。 c = ''然后c << 'G'比数组版本更高效,特别是考虑到数组将包含N个字符串,每个字符串都有一些开销,并且需要创建另一个最后使用join的字符串。使用Ruby时,尝试将临时或其他方面的计算所需的对象数量保持在最低限度。它通常更快,更少“垃圾”。

答案 1 :(得分:1)

后一种形式没有错,但考虑到ruby我们有unless我们应该在我们只有一个分支时使用它,这是优选的,就像在这种情况下一样。

无论如何,它完全一样。

答案 2 :(得分:0)

我认为这是课程的马匹...我和非常优秀的开发人员一起工作,他们的第一语言不是英语,他们发现If !(如果没有)更容易理解。

但Ruby样式指南https://github.com/bbatsov/ruby-style-guide特别喜欢unlessif !,但在unlesselse一起使用时会皱眉。

最后,最好将其重写为带有尾随条件的单行...

    return '' unless dna_structure.include? strand