似乎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? strand
和if !(dna_strucutre.include?)
之间有什么不同?
答案 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特别喜欢unless
到if !
,但在unless
与else
一起使用时会皱眉。
最后,最好将其重写为带有尾随条件的单行...
return '' unless dna_structure.include? strand