Rubocop犯罪:使用条件的返回值进行变量分配和比较

时间:2019-04-22 10:19:04

标签: ruby rubocop

我的Rubocop罪行告诉我,我需要“使用条件的返回值进行变量分配和比较”

当我尝试修复它时,这又给了我我“方法线太长”的冒犯。

我试图重构为另一种方法,但是我的代码坏了。

如何缩短或重构此代码?

HSH = { 'a' => 'z', 'b' => 'y', 'c' => 'x', 'd' => 'w', 'e' => 'v', \
        'f' => 'u', 'g' => 't', 'h' => 's', \
        'i' => 'r', 'j' => 'q', 'k' => 'p', 'l' => 'o', 'm' => 'n' }.freeze


def encoder(str)
  encoded_string = ''
  str.chars.each do |char|
    encoded_string = if HSH.key?(char) then encoded_string += HSH[char]
                     elsif HSH.invert.key?(char) then encoded_string += HSH.invert[char]
                     else encoded_string += char
                     end
  end
  encoded_string
end

运行测试套件时,一切正常。

但是鲁比科普犯罪给了我方法线太长。

6 个答案:

答案 0 :(得分:4)

无哈希:

// Setting the CartoDB tile (you can use any tile you want)
var tile = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
              bounds: [[-90,-180],[90,180]],
              attribution:'&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> &copy; <a href="http://cartodb.com/attributions">CartoDB</a>',
              subdomains:'abcd'
});

// Setting the map parameters
var map = L.map('map', {
        maxBounds: [[-90,-180],[90,180]],,
        minZoom: 0,
        maxZoom: 18,
        fullscreenControl: true
    })
    .addLayer(tile)
    .setView([0, 0], 12);

// Here the events for zooming and dragging
map.on('zoomend', function() {
   // stuff here when user zooms the map...
});
map.on('dragend', function() {
   // stuff here when user drags the map...    
});

答案 1 :(得分:2)

HSH = {
  'a' => 'z', 'b' => 'y', 'c' => 'x',
  'd' => 'w', 'e' => 'v', 'f' => 'u',
  'g' => 't', 'h' => 's', 'i' => 'r',
  'j' => 'q', 'k' => 'p', 'l' => 'o',
  'm' => 'n'
}.freeze

def encoder(str)
  str.chars.map { |char| HSH[char] || HSH.invert[char] || char }.join
end

答案 2 :(得分:1)

注意!不要使用此答案! @steenslag here提供了正确的解决方法。

使用哈希与所有明确映射的字母 和默认proc:

HSH =
  (?a..?z).zip((?a..?z).to_a.reverse).to_h.
  tap { |h| h.default_proc = ->(_, k) { k }}.
  freeze

def encoder(str)
  str.chars.map(&HSH.method(:[])).join
end

答案 3 :(得分:1)

我们中的一些人建议了更好的方法来实现您的encoder方法。但是我们所有人(包括我自己)都没有真正回答您的问题,或者在您的代码中看到了中心问题:

  

我的Rubocop罪行告诉我,我需要“使用条件的返回值进行变量分配和比较”

     

当我尝试修复它时,这又给了我我“方法线太长”的冒犯。

encoded_string = if HSH.key?(char) then encoded_string += HSH[char]
                 elsif HSH.invert.key?(char) then encoded_string += HSH.invert[char]
                 else encoded_string += char
                 end

您遵循了Rubocop的建议...您为一个值分配了条件结果...但我认为您错过了分数。我什至不确定那是它所指的条件结果。我假设您添加了encoded_string = ...分配。

这是一个无用的分配,因为您已经在if块内将字符附加到了encode_string上。您不必再次分配它。

回到我猜测的是您的版本1代码,这是遵循Rubocop的建议的一种更有效的方法。不要在每个条件内都进行赋值...只做一个赋值,条件是:

encoded_string += if HSH.key?(char) then HSH[char]
                  elsif HSH.invert.key?(char) then HSH.invert[char]
                  else char
                  end

最后,所需的代码更少,并且与您的原始编码风格和方法相匹配。它甚至可能使Rubocop高兴。可爱代码的下一步是消除过多的key?测试:

encoded_string += if HSH[char] then HSH[char]
                  elsif HSH.invert[char] then HSH.invert[char]
                  else char
                  end

从那里开始,用if/elsif消除||块是一小步。并且在进行处理时,我们将+=更改为<<以避免“产生大量中间不必要的String实例”。 (感谢您的建议,@ Aleksei Matiushkin)

encoded_string << HSH[char] || HSH.invert[char] || char

对于您解决此问题的方法,这就是生产代码应争取的最低程度的简洁性和可读性。任何人都可以理解它,而无需真正地努力或达到Stack Overflow。

答案 4 :(得分:0)

我会继续将您的哈希扩展到所有26个字母,这样您就可以避免反向查找。通过删除一种情况可以简化Rubocop,从而简化了代码。但是更重要的是,您将使用哈希索引来提高效率和性能。反向哈希查找非常昂贵,因为它必须读取(最多)每个值。

考虑编码为“ 1 + 2”。它将执行三个快速索引扫描,然后进行三个全数组扫描,只返回原始字符串。

使用完全填充的哈希,只需进行三个快速扫描即可。

以下是您的原始代码,其中进行了最小的更改以实现您的目标:(执行此操作的方法更短(提示:trmap),但是较短的代码不那么容易和舒适给使用代码的程序员。)

translation = { 
  'a' => 'z', 'b' => 'y', 'c' => 'x', 'd' => 'w', 'e' => 'v', 'f' => 'u', 'g' => 't', 
  'h' => 's', 'i' => 'r', 'j' => 'q', 'k' => 'p', 'l' => 'o', 'm' => 'n', 'n' => 'm', 
  'o' => 'l', 'p' => 'k', 'q' => 'j', 'r' => 'i', 's' => 'h', 't' => 'g', 'u' => 'f', 
  'v' => 'e', 'w' => 'd', 'x' => 'c', 'y' => 'b', 'z' => 'a'
}.freeze

def encoder(str)
  encoded_string = ''

  str.chars.each do |char|
    encoded_string << translation[char] || char
  end
  encoded_string
end

您甚至可以考虑将哈希扩展为大写和小写字母,甚至所有256个char值,具体取决于要解决的问题。但是,让我们同意忽略Unicode字符!

回到Rubocop ...对任何“太长/太复杂”警告的最简单,确定有效的解决方案是将代码提取到新方法中。编写def charswap并将其用作循环的主体。这将使编写测试变得更容易引导。但是,通过将翻译数组扩展到所有26个字母,代码变得如此简单,以至于真正不需要重构。

答案 5 :(得分:0)

与@Steenslag的答案一样,无需将字符串转换为数组,映射数组的每个元素并将结果重新组合为字符串。

def encode_decode(str)
  str.gsub(/./) { |c| ('a'..'z').cover?(c.ord) ? (219-c.ord).chr : c }
end

plain_text = "The launch code is 'Bal3De8Rd0asH'."
  #=> "Tsv ozfmxs xlwv rh 'Bzo3Dv8Rw0zhH'." 
encode_decode(coded_text)
  #=> "The launch code is 'Bal3De8Rd0asH'."  
相关问题