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?)
有什么不同? 最佳答案
由于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
,该方法是为处理字符之间存在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时,尽量减少计算所需的对象数量,不管是临时的还是其他的。用更少的“垃圾”通常更快。