删除满足条件

时间:2017-10-07 19:33:06

标签: ruby algorithm

我在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]

它会删除符合该条件的第一个元素,我需要删除最后一个元素。

1 个答案:

答案 0 :(得分:3)

@Steenslag和@Stefan对我的原始答案提出了同样的改进(虽然表达方式不同)。我已经编辑了我的答案以加入这种改进。

<强>代码

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]

<强>解释

示例中针对arrn的值执行的步骤如下。

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。剩下的计算是类似的。