Ruby 中的否定条件语句

Negative Conditional Statement in Ruby

似乎 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?) 有什么不同?

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

反正就是一模一样

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

但是 Ruby 风格指南 https://github.com/bbatsov/ruby-style-guide 特别喜欢 unless 而不是 if ! 但不赞成 unlesselse 一起使用。

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

    return '' unless dna_structure.include? strand 

因为 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 但这会产生三重否定。您已经在这里处理了一个双精度数,else 子句仅在字符串 not not 为空时才会发生,或者可以说 不不不包含任何内容.

改为这样做:

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

您在此处采用的方法存在许多问题,但最严重的问题是每次调用方法时您都在方法内声明了一个常量数组。由于它永远不会改变,因此它成为 class 级别顶部的常量。至少:

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

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

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

现在看看您尝试 "invert" 给定字符串的特定问题,您真正需要的工具是 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 时,尽量将进行计算所需的对象数量(无论是临时的还是其他方式)保持在最低限度。它通常更快,更少 "garbage".