AnA*_*ice 13 ruby ruby-on-rails ruby-on-rails-3
我有这样的哈希:
[
{
:lname => "Brown",
:email => "james@intuit.com",
:fname => "James"
},
{
:lname => nil,
:email => "brad@intuit.com",
:fname => nil
},
{
:lname => "Smith",
:email => "brad@intuit.com",
:fname => "Brad"
},
{
:lname => nil,
:email => "brad@intuit.com",
:fname => nil
},
{
:lname => "Smith",
:email => "brad@intuit.com",
:fname => "Brad"
},
{
:lname => nil,
:email => "brad@intuit.com",
:fname => nil
}
]
Run Code Online (Sandbox Code Playgroud)
我想学习如何删除记录是否重复.意思是,看看有几个"brad@intuit.com"如何删除重复的记录,意味着删除所有其他有电子邮件"brad@intuit.com"的人....将电子邮件作为密钥而不是其他字段?
Dan*_*ail 22
在Ruby 1.9.2中,Array#uniq将接受在比较对象时将使用的块参数:
arrays.uniq { |h| h[:email] }
Run Code Online (Sandbox Code Playgroud)
Har*_*tty 18
我知道这是一个旧线程,但是Rails在'Enumerable'上有一个名为'index_by'的方法,在这种情况下可以很方便:
list = [
{
:lname => "Brown",
:email => "james@intuit.com",
:fname => "James"
},
{
:lname => nil,
:email => "brad@intuit.com",
:fname => nil
},
{
:lname => "Smith",
:email => "brad@intuit.com",
:fname => "Brad"
},
{
:lname => nil,
:email => "brad@intuit.com",
:fname => nil
},
{
:lname => "Smith",
:email => "brad@intuit.com",
:fname => "Brad"
},
{
:lname => nil,
:email => "brad@intuit.com",
:fname => nil
}
]
Run Code Online (Sandbox Code Playgroud)
现在您可以获得如下唯一行:
list.index_by {|r| r[:email]}.values
Run Code Online (Sandbox Code Playgroud)
合并具有相同电子邮件ID的行.
list.group_by{|r| r[:email]}.map do |k, v|
v.inject({}) { |r, h| r.merge(h){ |key, o, n| o || n } }
end
Run Code Online (Sandbox Code Playgroud)
自定义但有效的方法:
list.inject({}) do |r, h|
(r[h[:email]] ||= {}).merge!(h){ |key, old, new| old || new }
r
end.values
Run Code Online (Sandbox Code Playgroud)
如果您将其直接放入数据库,只需validates_uniqueness_of :email在模型中使用即可.请参阅文档.
如果您在使用之前需要从实际哈希中删除它们,请执行以下操作:
emails = [] # This is a temporary array, not your results. The results are still in my_array
my_array.delete_if do |item|
if emails.include? item[:email]
true
else
emails << item[:email]
false
end
end
Run Code Online (Sandbox Code Playgroud)
更新:
这将合并重复条目的内容
merged_list = {}
my_array.each do |item|
if merged_list.has_key? item[:email]
merged_list[item.email].merge! item
else
merged_list[item.email] = item
end
end
my_array = merged_list.collect { |k, v| v }
Run Code Online (Sandbox Code Playgroud)