【问题标题】:comparing two arrays of hashes and making changes to one based off of result[Ruby]比较两个哈希数组并根据结果对一个数组进行更改[Ruby]
【发布时间】:2014-03-01 10:04:19
【问题描述】:

我有两个数组:

a = [{:name=>"John Doe", :number=>"555-234-5678", :count=>30}, {:name=>"Jane Doe", :number=>"555-456-1234", :count=>12}, {:name=>"Kobie Bryant", :number=>"555-621-9876", :count=>8}, {:name=>"JD", :number=>"555-234-5678", :count=>3}, {:name=>"KB", :number=>"555-621-9876", :count=>6}]

b = [{:name=>"JD", :number=>"555-234-5678", :count=>3}, {:name=>"KB", :number=>"555-621-9876", :count=>6}]

当 a[:name] 的首字母匹配 b[:name] 并且 a[:number] 匹配 b[:number] 时,我想将两个计数的总和添加到 a[:count],然后删除任何a 数组中 b 中元素的实例。

所以 a 的结果是:

a = [{:name=>"John Doe", :number=>"555-234-5678", :count=>33}, {:name=>"Jane Doe", :number=>"555-456-1234", :count=>12}, {:name=>"Kobie Bryant", :number=>"555-621-9876", :count=>14}]

到目前为止,我有:

h = []
b.each do |double|
    a.each do |conn|
        if (double[:name][0,1] == conn[:name][0,1].split[0,1]) && (double[:name][1,1] == conn[:name][1,1].split[0,1])
            h[double] += conn[:count] + b[:count]
            a.delete(conn)
        end
    end
end

非常感谢任何帮助。谢谢大家!

【问题讨论】:

  • 再次检查您的ab 数组。输出没有说明确切的逻辑。怎么33这里{:name=>"John Doe", :number=>"555-234-5678", :count=>33}
  • John Doe 的数量 = 30 + JD 的数量 = 3。由于它们的数量相同,所以 John Doe 的数量就是总和。

标签: ruby arrays hash


【解决方案1】:

我建议你把这个过程分解一下。

def initials_from(name)
  name.split(" ").map { |name| name[0] }.join("")
end

def is_dup?(first, second)
  first == second
end

def matches?(first, second)
  initials_from(first[:name]) == second[:name] &&
    first[:number] == second[:number]
end

combined_result = a.each_with_object([]) { |first, result|
  # Skip duplicates
  duplicate = b.detect { |b_member| is_dup?(first, b_member) }
  next unless duplicate.nil?

  matching = b.detect { |b_member| matches?(first, b_member) }

  if matching
    combined = first.dup
    combined[:count] = first[:count] + matching[:count]
    result.push(combined)
  else
    result.push(first)
  end
}

combined_result
# [
#   {:name=>"John Doe",     :number=>"555-234-5678", :count=>33},
#   {:name=>"Jane Doe",     :number=>"555-456-1234", :count=>12},
#   {:name=>"Kobie Bryant", :number=>"555-621-9876", :count=>14}
# ]

然后,如果您真的想就地修改 a 而不是获取新数组:

a.replace(combined_result)

【讨论】:

    【解决方案2】:

    我会这样做:

    a = [{:name=>"John Doe", :number=>"555-234-5678", :count=>30}, {:name=>"Jane Doe", :number=>"555-456-1234", :count=>12}, {:name=>"Kobie Bryant", :number=>"555-621-9876", :count=>8}, {:name=>"JD", :number=>"555-234-5678", :count=>3}, {:name=>"KB", :number=>"555-621-9876", :count=>6}]
    
    b = [{:name=>"JD", :number=>"555-234-5678", :count=>3}, {:name=>"KB", :number=>"555-621-9876", :count=>6}]
    
    ary = a.group_by do |inner_hash|
      name = inner_hash[:name]
      [/([A-Z])(?:\w+\s+)?([A-Z])/.match(name).captures.join , inner_hash[:number]]
    end
    
    array_of_hash = ary.flat_map do |k,v|
      bol = b.select do |hash|
        name = hash[:name]
        [/([A-Z])(?:\w+\s+)?([A-Z])/.match(name).captures.join , hash[:number]] == k
      end.empty?
      unless bol
        count = v.inject(0) { |sum,h1| sum = sum + h1[:count] }
        max_val_string = v.max_by { |h| h[:name].size }[:name]
      end
      next {:name => max_val_string, :number => k.last , :count => count} unless bol
      v
    end
    array_of_hash
    # => [{:name=>"John Doe", :number=>"555-234-5678", :count=>33},
    #     {:name=>"Jane Doe", :number=>"555-456-1234", :count=>12},
    #     {:name=>"Kobie Bryant", :number=>"555-621-9876", :count=>14}]
    

    【讨论】:

      【解决方案3】:

      假设b 中的[:name, :number] 是唯一的(如果不是,则需要稍作修改):

      b_index = Hash[b.map { |x| [x.values_at(:name, :number), x[:count]] }]
      b_index.default = 0
      
      r = 
        a.reject { |x| 
          b_index.has_key?(x.values_at(:name, :number)) 
        } \
        .map { |x| 
          name, number = x.values_at(:name, :number)
          initials = name.split(/\s+/).map { |y| y[0] }.join 
          x[:count] += b_index[[initials, number]]
          x
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-04-03
        • 2012-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-03
        • 1970-01-01
        相关资源
        最近更新 更多