我在Kata上工作。给定列表lst
和数字N
,我创建了一个新列表,其中包含lst
的每个元素最多N
次而无需重新排序。例如,如果N = 2
,输入为[1,2,3,1,2,1,2,3]
,我会[1,2,3,1,2]
,删除下一个[1,2]
,因为这会导致1
和{{1}在结果中进行3次,然后选择2
,这会导致3
。
这是我的代码:
[1,2,3,1,2,3]
这是输出。
从数组[20,37,20,21],你得到1 - 预期:[20,37,21],而不是 得到:[37,20,21]
它会删除符合该条件的第一个元素,我需要删除最后一个元素。
答案 0 :(得分:3)
<强>代码强>
def doit(arr, n)
h = Hash.new(0)
arr.select { |e| n >= h[e] += 1 }
end
示例强>
arr = [1,2,3,1,2,1,2,3]
n = 2
doit arr, n
#=> [1, 2, 3, 1, 2, 3]
<强>解释强>
示例中针对arr
和n
的值执行的步骤如下。
h = Hash.new(0)
这是Hash::new的形式,它采用默认值,此处为零。这意味着如果上面定义的h
没有键k
,则会返回默认值:
h['cat'] #=> 0
这不会改变哈希值。如果我们现在写h[:a] = 1
(所以h=>{:a=>1}
),那么h[:a]
会返回1
,因为h
现在有一个键:a
。接着,
enum = arr.reject
# => #<Enumerator: [1, 2, 3, 1, 2, 1, 2, 3]:reject>
第一个值由enum
生成并传递给块,并为块变量赋值。
e = enum.next
#=> 1
现在执行块计算
h[e] += 1
#=> h[e] = h[e] + 1
# h[e] = 0 + 1 = 1
所以现在
h #=> { 1=>1 }
因为
2 >= h[1]
#=> true
选择arr
的第一个元素。
关于表达式h[1] = h[1] + 1
,有两点需要注意。首先,因为h
没有键1
,所以在等式右边的h[1]
返回默认值零。其次,方法Hash#[]使用默认值,而不是Hash#[]=(等号左侧)。
enum
的第二个值现在传递给块,并执行类似的计算。
e = enum.next
#=> 2
h[e] += 1
#=> h[2] = h[2] + 1
# h[2] = 0 + 1
h #=> {1=>1, 2=>1}
2 >= h[2]
#=> true
因此,arr
的第二个元素也被选中。让我们跳过enum
:
enum.next
#=> 3
enum.next
#=> 1
enum.next
#=> 2
此时
h = { 1=>2, 2=>2, 3=>1 }
并且该块已为5
生成的每个第一个enum
元素返回了一个真值。
接下来,
e = enum.next
#=> 1
h[e] += 1
#=> h[1] = h[1] + 1
# h[1] = 2 + 1
h #=> {1=>3, 2=>2, 3=>1}
2 >= h[1]
#=> 2 >= 3 => false
因此未选择此值1
。剩下的计算是类似的。