ruby使用某些键比较两个哈希数组

时间:2015-05-27 23:36:37

标签: ruby-on-rails ruby

有两个哈希数组,我想根据某些键从两个数组中删除'common'元素。例如:

array1-array2 (don't have to overwrite '-' if there's better approach)

标准键是 a b 。所以当我得到像

这样的结果时
CREATE TABLE CASEDETAIL ( CaseNumber, CaseType ) AS
          SELECT 1, 'RelevantToThisQuestion' FROM DUAL
UNION ALL SELECT 2, 'RelevantToThisQuestion' FROM DUAL
UNION ALL SELECT 3, 'RelevantToThisQuestion' FROM DUAL
UNION ALL SELECT 4, 'NotRelevantToThisQuestion' FROM DUAL;

CREATE TABLE LINKEDPEOPLE ( CaseNumber, RelationshipType, LinkedPerson ) AS
          SELECT 1, 'Owner', 123 FROM DUAL
UNION ALL SELECT 1, 'Agent', 124 FROM DUAL
UNION ALL SELECT 1, 'Contact', 125 FROM DUAL
UNION ALL SELECT 2, 'Owner', 126 FROM DUAL
UNION ALL SELECT 2, 'Agent', 127 FROM DUAL
UNION ALL SELECT 2, 'Contact', 128 FROM DUAL
UNION ALL SELECT 3, 'Owner', 129 FROM DUAL
UNION ALL SELECT 3, 'Agent', 130 FROM DUAL
UNION ALL SELECT 3, 'Contact', 131 FROM DUAL;

CREATE TABLE LOCATION ( LinkedPerson, Country ) AS
          SELECT 123, 'AU' FROM DUAL
UNION ALL SELECT 124, 'UK' FROM DUAL
UNION ALL SELECT 125, 'UK' FROM DUAL
UNION ALL SELECT 126, 'US' FROM DUAL
UNION ALL SELECT 127, 'US' FROM DUAL
UNION ALL SELECT 128, 'UK' FROM DUAL
UNION ALL SELECT 129, 'UK' FROM DUAL
UNION ALL SELECT 130, 'AU' FROM DUAL
UNION ALL SELECT 131, 'UK' FROM DUAL;
它会期望得到     [{a:'4',b:'5',c:'6'}] 我们正在使用a和b作为比较标准。它将擦除第二个元素,因为对于array1.last和array2.last,a的值是不同的。

2 个答案:

答案 0 :(得分:8)

据我了解,您将获得两个哈希数组和一组键。对于所有指定的键,您希望拒绝第一个数组的所有元素(哈希),其值与第二个数组的任何元素(哈希值)匹配。你可以这样做。

<强>代码

require 'set'

def reject_partial_dups(array1, array2, keys)
  set2 = array2.each_with_object(Set.new) do |h,s|
     s << h.values_at(*keys) if (keys-h.keys).empty? 
  end
  array1.reject do |h|
    (keys-h.keys).empty? && set2.include?(h.values_at(*keys))
  end
end

该行:

(keys-h.keys).empty? && set2.include?(h.values_at(*keys))

可以简化为:

set2.include?(h.values_at(*keys))

如果array1的元素(哈希)中的键值都不是nil。我从array2创建了一个集合(而不是数组),以加快该行中h.values_at(*keys)的查找速度。

示例

keys = [:a, :b]
array1 = [{a: '1', b:'2', c:'3'}, {a: '4', b: '5', c:'6'}, {a: 1, c: 4}]
array2 = [{a: '1', b:'2', c:'10'}, {a: '3', b: '5', c:'6'}]
reject_partial_dups(array1, array2, keys)
  #=> [{:a=>"4", :b=>"5", :c=>"6"}, {:a=>1, :c=>4}] 

<强>解释

首先创建set2

e0 = array2.each_with_object(Set.new)
  #=> #<Enumerator: [{:a=>"1", :b=>"2", :c=>"10"}, {:a=>"3", :b=>"5", :c=>"6"}]
  #     #:each_with_object(#<Set: {}>)> 

传递e0的第一个元素并执行块计算。

h,s = e0.next
  #=> [{:a=>"1", :b=>"2", :c=>"10"}, #<Set: {}>]
h #=> {:a=>"1", :b=>"2", :c=>"10"} 
s #=> #<Set: {}> 
(keys-h.keys).empty?
  #=> ([:a,:b]-[:a,:b,:c]).empty? => [].empty? => true

所以计算:

s << h.values_at(*keys)
  #=> s << {:a=>"1", :b=>"2", :c=>"10"}.values_at(*[:a,:b] }
  #=> s << ["1","2"] => #<Set: {["1", "2"]}> 

e0的第二个(最后一个)元素传递给块:

h,s = e0.next
  #=> [{:a=>"3", :b=>"5", :c=>"6"}, #<Set: {["1", "2"]}>] 
(keys-h.keys).empty?
  #=> true

所以计算:

s << h.values_at(*keys)
  #=> #<Set: {["1", "2"], ["3", "5"]}> 

set2
  #=> #<Set: {["1", "2"], ["3", "5"]}> 

拒绝来自array1 的元素

我们现在遍历array1,拒绝块评估为true的元素。

e1 = array1.reject
  #=> #<Enumerator: [{:a=>"1", :b=>"2", :c=>"3"},
  #                  {:a=>"4", :b=>"5", :c=>"6"}, {:a=>1, :c=>4}]:reject> 

e1的第一个元素传递给块:

h = e1.next
  #=> {:a=>"1", :b=>"2", :c=>"3"} 
a = (keys-h.keys).empty?
  #=> ([:a,:b]-[:a,:b,:c]).empty? => true
b = set2.include?(h.values_at(*keys))
  #=> set2.include?(["1","2"] => true
a && b
  #=> true

所以e1的第一个元素被拒绝了。下一个:

 h = e1.next
   #=> {:a=>"4", :b=>"5", :c=>"6"} 
 a = (keys-h.keys).empty?
   #=> true 
 b = set2.include?(h.values_at(*keys))
   #=> set2.include?(["4","5"] => false
 a && b
   #=> false

所以e1的第二个元素不会被拒绝。最后:

h = e1.next
  #=> {:a=>1, :c=>4} 
a = (keys-h.keys).empty?
  #=> ([:a,:c]-[:a,:b]).empty? => [:c].empty? => false

所以返回true(意味着e1的最后一个元素不被拒绝),因为不需要计算:

 b = set2.include?(h.values_at(*keys))

答案 1 :(得分:1)

所以你真的应该自己尝试一下,因为我基本上是为你解决的。

一般方法是:

  1. 每次都在array1
  2. 检查array2中的相同值是否具有任何具有相同值的键和值
  3. 如果他们这样做,请将其删除
  4. 您最终可能会遇到类似array1.each_with_index { |h, i| h.delete_if {|k,v| array2[i].has_key?(k) && array2[i][k] == v } }

    的内容