嵌套If语句的Ruby方式

嵌套If语句的Ruby方式,ruby,Ruby,现在,我觉得把变量设置为一个值是一种非常丑陋的方式,取决于它是否返回空字符串。下面是讨论中的方法(它使用Nokogiri,但这对这个问题并不重要) 移除返回并让: def get_let(response) if response.css('A').empty? response.css('B').empty? ? '' : response.css('B') else response.css('A') end end 或使用集合: d

现在,我觉得把变量设置为一个值是一种非常丑陋的方式,取决于它是否返回空字符串。下面是讨论中的方法(它使用Nokogiri,但这对这个问题并不重要)

移除返回并让:

def get_let(response)
    if response.css('A').empty?
        response.css('B').empty? ? '' : response.css('B')
    else
        response.css('A')
    end
end
或使用集合:

def get_let(response)
    ['A', 'B'].map { |l| response.css(l) }.find { |items| !items.empty? } || ''
end

避免两次计算CSS选择器。

我会这样做,非常明确地说明发生了什么,在推理时没有分支逻辑来跟踪它

def get_let(response)
    return '' if response.css('A').empty? && response.css('B').empty?
    return response.css('B') if response.css('A').empty?
    return response.css('A') if response.css('B').empty?
end

您不需要
让它返回if/else块的结果就可以了。。。我更喜欢这样保存它,因为它比ternaries更容易阅读

def get_let(response)
  if response.css('A').empty?
    if response.css('B').empty?
      ''
    else
      response.css('B')
    end
  else
    response.css('A')
  end
end

这并不像@sethcall的答案那么易读,但如果您知道一些Ruby习惯用法,它应该是相当易读的:

def get_let(response)
  responses = [response.css('A'), response.css('B')]
  responses.detect { |response| !response.empty? } || ''
end
detect
返回块未返回false的第一个结果。这有避免条件句的优点,如果你想要的话。如果不想使用上述答案中的
|
,可以执行以下操作:

def get_let(response)
  responses = [response.css('A'), response.css('B')]
  responses.detect(-> { '' }) { |response| !response.empty? }
end
不过,我觉得第二种解决方案不如第一种解决方案直观。如果您可以指定一个空字符串作为参数,那将是非常棒的。但是,
detect
及其别名
find
的参数必须是
nil
或响应
调用
方法的参数,如lambda或proc。实际上没有理由传入
nil
,因为这是默认值

如果您确信response.css方法不会返回包含
nil
false
值的数组,则可以尝试以下解决方案:

def get_let(response)
  responses = [response.css('A'), response.css('B')]
  responses.detect(&:any?) || ''
end

请参阅Ruby文档以了解更多信息。以下是.

您的问题是什么?如果response.css('A')和response.css('B')都为空,则
find
的默认参数将引发此异常:
NoMethodError:undefined方法“call”for“”:String
find
及其别名
detect
要求参数1)为
nil
,或2)响应
调用
。查看我的答案,了解收集方法的一些替代实现。尼斯,忘记了这一点。这种方法的两个缺点是它有多个返回,并且返回是隐式的。如果您有一个方法的多个返回点,我建议使用
return
关键字来明确它们。我知道
return
通常不是很rubysh,但在这种情况下我会破例,因为使用它可以澄清代码。如果您使用Rails或ActiveSupport,您可以将其缩短为
响应。检测(&:present)| |“
def get_let(response)
  responses = [response.css('A'), response.css('B')]
  responses.detect { |response| !response.empty? } || ''
end
def get_let(response)
  responses = [response.css('A'), response.css('B')]
  responses.detect(-> { '' }) { |response| !response.empty? }
end
def get_let(response)
  responses = [response.css('A'), response.css('B')]
  responses.detect(&:any?) || ''
end