如何在考虑每个值唯一的情况下基于数组散列过滤数组?

时间:2018-01-12 23:50:00

标签: ruby

在我的一个项目中,我正在尝试过滤新收集的信息,这些信息还包含上一个请求中的所有数据。有了这个过滤后的数据,我想将它作为新数组添加到旧数据中。新数据作为数组出现,旧数据保存在数组散列中。

我尝试了许多不同的方法来从当前数据中删除所有过去的数据点失败。这里一个重要的细节是新数据可能包含与旧数据匹配的重复值,但在技术上是新的,应该被视为唯一。

以下是一个示例数据集:

x = {
  'a' => [],
  'b' => [1],
  'c' => [],
  'd' => [2, 3, 1, 5, 6, 3]
}
y = [0, 2, 3, 5, 1, 5, 6, 3, 1, 10, 7]

z = [0, 5, 10, 7]

x是旧数据,y是新数据。所需的过滤输出为z,然后将其添加到x,为我们提供:

x = {
  'a' => [],
  'b' => [1],
  'c' => [],
  'd' => [2, 3, 1, 5, 6, 3]
  'e' => [0, 5, 10, 7]
}

我需要根据其他一些标准继续重复这一点。

这里的主要障碍是正确完成过滤,对我来说一直很困难。这是我尝试的一些事情的列表:

我已经尝试迭代哈希的键,然后simply subtracting数组,但不幸的是,它也无法正常工作,因为它也不再重复。

irb(main):024:0> d = [2, 3, 1, 5, 6, 3]
=> [2, 3, 1, 5, 6, 3]
irb(main):025:0> y = [0, 2, 3, 5, 1, 5, 6, 3, 1, 10, 7]
=> [0, 2, 3, 5, 1, 5, 6, 3, 1, 10, 7]
irb(main):026:0> y - d
=> [0, 10, 7]

我已经尝试了工会

irb(main):029:0> y | d
=> [0, 2, 3, 5, 1, 6, 10, 7]

和十字路口。 (这绝对是错误的)

irb(main):030:0> y & d
=> [2, 3, 5, 1, 6]

我尝试(未成功)从第二个comment here

实施以下内容
class Array
  def delete_elements_in(ary)
    ary.each do |x|
      if index = index(x)
        delete_at(index)
      end
  end
end

我也试过reject!

irb(main):057:0> x = { 'a' => [], 'b' => [1], 'c' => [], 'd' => [2, 3, 1, 5, 6, 3] }
=> {"a"=>[], "b"=>[1], "c"=>[], "d"=>[2, 3, 1, 5, 6, 3]}
irb(main):058:0> y = [0, 2, 3, 5, 1, 5, 6, 3, 1, 10, 7]
=> [0, 2, 3, 5, 1, 5, 6, 3, 1, 10, 7]
irb(main):059:0> x.each_key { |key| y.reject! { |v| a[key].index(v) } }
=> {"a"=>[], "b"=>[1], "c"=>[], "d"=>[2, 3, 1, 5, 6, 3]}
irb(main):060:0> y
=> [0, 10, 7]

我最近尝试从x的所有值创建一个新数组,然后对y使用该数组,但尝试失败。我最近想过试图保留一系列“看到”的数字,但我仍然坚持实际需要删除的项目,即使重复。

在整个过程中,我一直无法获得[0, 5, 10, 7]

HALP!

2 个答案:

答案 0 :(得分:3)

这里有一些可能对你有用的东西:

>> existing = x.values.flatten
#> [1, 2, 3, 1, 5, 6, 3]
>> z = y.dup # This avoids altering the original `y` array
>> existing.each { |e| z.delete_at(z.index(e)) if z.index(e) }
>> z
#> [0, 5, 10, 7] # z now contains the desired result

>> x['e'] = z
>> pp x
{"a"=>[],
 "b"=>[1],
 "c"=>[],
 "d"=>[2, 3, 1, 5, 6, 3],
 "e"=>[0, 5, 10, 7]}

以下是一个方法:

def unique_array_filter(hash, new_array)
  existing = hash.values.flatten
  next_key = hash.keys.max.next
  temp = new_array.dup

  existing.each { |e| temp.delete_at(temp.index(e)) if temp.index(e) }

  hash[next_key] = temp
  hash
end

>> unique_array_filter(x, y)
#> {"a"=>[], "b"=>[1], "c"=>[], "d"=>[2, 3, 1, 5, 6, 3], "e"=>[0, 5, 10, 7]}

答案 1 :(得分:1)

x.merge(x.keys.max.next => y.difference(x.values.flatten))
  #=> {"a"=>[], "b"=>[1], "c"=>[], "d"=>[2, 3, 1, 5, 6, 3], "e"=>[0, 5, 10, 7]}

其中Array#difference的定义如下。

class Array
  def difference(other)
    h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
    reject { |e| h[e] > 0 && h[e] -= 1 }
  end
end

请参阅链接以获取Array#difference的解释。