Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 分配分支条件大小太大_Ruby_Rubocop - Fatal编程技术网

Ruby 分配分支条件大小太大

Ruby 分配分支条件大小太大,ruby,rubocop,Ruby,Rubocop,我正在创建一个方法,它接受多行字符串日志并将新字符串写入数组 def task_2(str) result = [] str.each_line do |x| ip = x[/^.* - -/] datetime = x[/[\[].*[\]]/] address = x[/T .* H/] if !ip.nil? && !datetime.nil? && !address.nil? result <<

我正在创建一个方法,它接受多行字符串日志并将新字符串写入数组

def task_2(str)
  result = []
  str.each_line do |x|
    ip = x[/^.* - -/]
    datetime = x[/[\[].*[\]]/]
    address = x[/T .* H/]
    if !ip.nil? && !datetime.nil? && !address.nil?
      result << datetime[1..-2] + ' FROM: ' + ip[0..-4] + 'TO:' + address[1..-3]
    end
  end
  result
end

我不使用rubocop,但我用这些数据测试了以下内容:

data = <<FILE
10.6.246.103 - - [23/Apr/2018:20:30:39 +0300] "POST /test/2/messages HTTP/1.1" 200 48 0.0498
10.6.246.101 - - [23/Apr/2018:20:30:42 +0300] "POST /test/2/run HTTP/1.1" 200 - 0.2277
12.55.123.255 - - Hello
FILE
我们正在使用StringSub!使用模式替换,如果没有进行替换,将返回nil,从而从Enumerableselect中拒绝它

使用Stringmatch、Enumerablemap和Arraycompact报告AbcSize 7.14的类似解决方案,尽管效率可能较低

可以使最后一个低至2.24通过


有!变量0.nil?这是多余的。基本上,你是在检查这里的存在,那么现在呢?方法就足够了,但是任何不是nil或false的值都被认为是false,所以为了更习惯,最好只使用if语句中使用的形式。这解决了ABS问题。

通过执行以下操作计算ABC尺寸:

√(assignments² + branches² + conditionals²)
让我们先看一下作业:

result = []
ip = x[/^.* - -/]
datetime = x[/[\[].*[\]]/]
address = x[/T .* H/]
这给我们留下了4个作业

接下来是树枝。对于这一点,我必须提到的是,大多数运算符都是方法,因此可以对分支计数,例如1+1也可以写成1。+1+是一个整数上的方法。字符串[regex]也是如此,它也可以写成字符串。[]regex[]是字符串上的一个方法。让我们数一数树枝

str.each_line
x[/^.* - -/]
x[/[\[].*[\]]/]
x[/T .* H/]
!ip.nil? # counts for 2 (! and .nil?)
!datetime.nil? # counts for 2 (! and .nil?)
!address.nil? # counts for 2 (! and .nil?)
result << ...
datetime[1..-2]
ip[0..-4]
address[1..-3]
+ # 4 times in result << ... + ... + ....
这给我们留下了3个条件

if
&& # 2 times
√(4² + 18² + 3²) ≈ 18.68
现在我们已经了解了这个数字的来源,我们可以尝试减少它。减少ABC大小最简单的方法是减少最大数字的事物,因为这个数字是平方的。在你的情况下,这些是分支。你已经发现了问题的症结所在

if !ip.nil? && !datetime.nil? && !address.nil?
  result << datetime[1..-2] + ' FROM: ' + ip[0..-4] + 'TO:' + address[1..-3]
end

每当我遇到ABC过高或类似的复杂性/长度警告时,我都会很快地将该方法切碎。您的可读性、可测试性和可维护性几乎总是在提高

最快的方法是将循环体或条件体拖到新方法中。根据需要重复,直到你能一口气阅读每种方法

类似地,如果您有大型复杂条件/循环构造,也可以将其拉到新方法中

将这两种策略结合足够的时间,可以将任何方法简化为大约两个方法调用。在某些情况下,这可能有点过分热情……但这永远不会太过分

以下是一种将该策略应用于代码的方法:

def task_2(str)
  result = []

  str.each_line do |x|
    ip, datetime, address = parse_line(x)

    if [ip, datetime, address].all?
      result << "#{datetime[1..-2]} FROM: #{ip[0..-4]} TO: #{address[1..-3]}"
    end
  end

  result
end

def parse_line(x)
  ip = x[/^.* - -/]
  datetime = x[/[\[].*[\]]/]
  address = x[/T .* H/]
  return [ip, datetime, address]
end

s =<<EOF
123.123.123.999 - - [2009-12-31 13:13:13] T www.google.com H"
456.456.456.999 - - [2009-12-31 13:13:13] 404"
678.678.678.999 - - [2009-12-31 13:13:13] T www.amazon.com H"
EOF

puts task_2(s)

如果你想走得更远,你可以把每一行的主体拉到一个新的方法,进程,等等。如果你创建了一个类,你可以避免混乱的多值返回

这是一个使用命名捕获组比较方便的问题

R = /
    (?=                       # begin a positive lookahead
      (?<ip>.*\s-\s-)         # match the string in a capture group named 'ip' 
    )                         # end positive lookahead
    (?=                       # begin a positive lookahead
      .*                      # match any number of characters
      (?<datetime>[\[].*[\]]) # match the string in a capture group named 'datetime'
    )                         # end positive lookahead
    (?=                       # begin a positive lookahead
      .*                      # match any number of characters
      (?<address>T\s.*\sH)    # match the string in a capture group named 'address' 
    )                         # end positive lookahead
    /x                        # free-spacing regex definition mode
正则表达式按惯例编写如下

R = /(?=(?<ip>\A.* - -))(?=.*(?<datetime>[\[].*[\]]))(?=.*(?<address>T .* H))/

请注意,当以自由间距模式编写正则表达式时,此处有空格的地方有空白字符\s。这是因为在自由间距模式中,空间在表达式求值之前被剥离。或者,通过将空格包含在字符类[]中,可以在自由间距模式下保留空格。

Wow。很好的解释。介意给我简要解释一下原因吗。r=[];str.scan/^[\d+\.\d+]++.@engineersmnky您有1个赋值r=[],2个分支str.scan,r@engineersmnky您必须记住,块参数不是由您分配的,而是由调用块的代码分配的,这意味着ip、日期、时间和地址是由扫描方法分配的。此外,Ruby对方法有点棘手,因为我当然知道方法调用是什么。更让我感到困惑的是,任务显然发生在街区层面,尽管是暂时的。我只是假设我建议的each_line.select选项会有最低的结果,并在没有结果时感到困惑,但现在它是有意义的,因为涉及到3个分支。虽然是一个干净的解决方案,但我不能给这个a+1,因为OP方法的变化很大,OP可能不知道发生了什么。@3limin4t0r很好,也许我接受了但是我怎样才能重写它呢?有点过分:@davidhampy,我相信你不会介意我用你的例子。睡衣。我不使用机器人战车,所以你能告诉我我的代码的AbcSize吗?任务的AbcSize_2:15.07
if
&& # 2 times
√(4² + 18² + 3²) ≈ 18.68
if !ip.nil? && !datetime.nil? && !address.nil?
  result << datetime[1..-2] + ' FROM: ' + ip[0..-4] + 'TO:' + address[1..-3]
end
if ip && datetime && address
  result << "#{datetime[1..-2]} FROM: #{ip[0..-4]}TO:#{address[1..-3]}"
end
√(4² + 8² + 3²) ≈ 9.43
def task_2(str)
  result = []

  str.each_line do |x|
    ip, datetime, address = parse_line(x)

    if [ip, datetime, address].all?
      result << "#{datetime[1..-2]} FROM: #{ip[0..-4]} TO: #{address[1..-3]}"
    end
  end

  result
end

def parse_line(x)
  ip = x[/^.* - -/]
  datetime = x[/[\[].*[\]]/]
  address = x[/T .* H/]
  return [ip, datetime, address]
end

s =<<EOF
123.123.123.999 - - [2009-12-31 13:13:13] T www.google.com H"
456.456.456.999 - - [2009-12-31 13:13:13] 404"
678.678.678.999 - - [2009-12-31 13:13:13] T www.amazon.com H"
EOF

puts task_2(s)
2009-12-31 13:13:13 FROM: 123.123.123.999  TO:  www.google.com
2009-12-31 13:13:13 FROM: 678.678.678.999  TO:  www.amazon.com
R = /
    (?=                       # begin a positive lookahead
      (?<ip>.*\s-\s-)         # match the string in a capture group named 'ip' 
    )                         # end positive lookahead
    (?=                       # begin a positive lookahead
      .*                      # match any number of characters
      (?<datetime>[\[].*[\]]) # match the string in a capture group named 'datetime'
    )                         # end positive lookahead
    (?=                       # begin a positive lookahead
      .*                      # match any number of characters
      (?<address>T\s.*\sH)    # match the string in a capture group named 'address' 
    )                         # end positive lookahead
    /x                        # free-spacing regex definition mode
def task_2(str)
  str.each_line.with_object([]) do |s, result|
    m = str.match(R)
    result << m[:datetime][1..-2] + ' FROM: ' + m[:ip][0..-4] +
              'TO:' + m[:address][1..-3] unless m.nil?      
  end
end
str =<<_
123.123.123.999 - - [2009-12-31 13:13:13] T www.google.com H"
456.456.456.999 - - [2009-12-31 13:13:13] 404"
678.678.678.999 - - [2009-12-31 13:13:13] T www.amazon.com
_
task_2 str
  #=> ["2009-12-31 13:13:13 FROM: 123.123.123.999 TO: www.google.com",
  #    "2009-12-31 13:13:13 FROM: 123.123.123.999 TO: www.google.com",
  #    "2009-12-31 13:13:13 FROM: 123.123.123.999 TO: www.google.com"] 
R = /(?=(?<ip>\A.* - -))(?=.*(?<datetime>[\[].*[\]]))(?=.*(?<address>T .* H))/