所以我目前正在处理代码大战中的以下问题:
返回一个数组,其中第一个元素是正数的数量,第二个元素是负数的总和。如果输入数组为空或null,则返回一个空数组。
我提出了以下代码,它很不错,但我知道它应该可行:
def count_positives_sum_negatives(lst)
pos, neg = 0, 0
lst.each do |num|
if num < 0
neg += num
else
pos++
end
end
[pos, neg]
end
然后我调用以下测试:
count_positives_sum_negatives([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -11, -12, -13, -14, -15])
它应该返回=&gt; [10,-65]
然而它返回以下错误:
(repl):11: syntax error, unexpected keyword_end
(repl):17: syntax error, unexpected end-of-input, expecting keyword_end
..., 10, -11, -12, -13, -14, -15])
...
有人能解释一下为什么会这样吗?
答案 0 :(得分:7)
正如人们已经指出这里的错误是x++
不是有效的Ruby,你需要x +=1
。后缀和前缀增量运算符在大多数语言中都是一个混乱的点,因此Ruby从未实现过。同样,x++ + x++ + ++x
的结果是什么?
使用partition
首先拆分数组,然后使用inject
将其折叠在一起,这是一个不同的策略:
positives, negatives = list.partition(&:positive?)
[ positives.length, negatives.inject(0, &:+) ]
# => [10,-65]
答案 1 :(得分:4)
这是你可以做到的另一种方式。
def count_pos_sum_neg(arr)
return [] if arr.empty?
arr.each_with_object([0,0]) do |n,a|
a[0] += 1 if n > 0
a[1] += n if n < 0
end
end
count_pos_sum_neg [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -11, -12, -13, -14, -15]
#=> [10, -65]
在实际应用中,返回哈希可能更方便。
def count_pos_sum_neg(arr)
return [] if arr.empty?
arr.each_with_object({count_pos: 0, sum_neg: 0}) do |n,h|
h[:count_pos] += 1 if n > 0
h[:sum_neg] += n if n < 0
end
end
count_pos_sum_neg [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -11, -12, -13, -14, -15]
#=> {:count_pos=>10, :sum_neg=>-65}
答案 2 :(得分:2)
问题是pos++
,这不是Ruby中的有效操作。它被解释为一个加法后跟一元+
,但是在一元之后没有数字,所以它期望下一行包含一个值。
但下一行是end
,这是意外的(因此是第一个错误unexpected keyword_end
),因为现在消耗了end
,你错过了方法的结束(因此第二行)错误expecting keyword_end
所以只需将行改为......
pos += 1
答案 3 :(得分:1)
另一种使用inject
的变体:
def count_pos_sum_neg(arr)
arr.inject([0, 0]) do |(count, sum), n|
if n > 0
[count + 1, sum]
else
[count, sum + n]
end
end
end
或压缩:
def count_pos_sum_neg(arr)
arr.inject([0, 0]) { |(c, s), n| n > 0 ? [c + 1, s] : [c, s + n] }
end
代码不检查“如果输入数组为空或为空”。
答案 4 :(得分:0)
我怀疑你最初的方法很容易阅读和简单,实际上也很快。 fruity比较(代码压缩)的一些结果:
require 'fruity'
arr = ((-1000..-1).to_a + (1..1000).to_a).shuffle
#various methods etc as defined in other answers.
compare do
wnamen { ar = arr; wnamen_method ar }
tadman { ar = arr; tadman_method ar }
cary { ar = arr; cary_method ar }
cary2 { ar = arr; cary2_method ar }
stefan { ar = arr; stefan_method ar }
stefan2 { ar = arr; stefan2_method ar }
end
结果:
Running each test 8 times. Test will take about 1 second.
wnamen is faster than tadman by 2.0x ± 0.1
tadman is similar to stefan2
stefan2 is similar to stefan
stefan is similar to cary
cary is faster than cary2 by 19.999999999999996% ± 10.0% (results differ: [1000, -500500] vs {:count_pos=>1000, :sum_neg=>-500500})
所有其他方法当然都很有趣,但仍然值得了解。