合并Ruby数组
我有几个类为合并Ruby数组,ruby,arrays,merge,Ruby,Arrays,Merge,我有几个类为UserInfo的Ruby对象数组: class UserInfo attr_accessor :name, :title, :age end 如何将这些数组合并到一个数组中?用户由其名称标识,因此我不希望有重复的名称。如果姓名、头衔、年龄等相等,我希望在新数组中有1个条目。如果名称相同,但任何其他细节不同,我可能希望位于不同阵列中的这两个用户手动修复错误 提前感谢一年前对象上的一种神秘的实例变量\u比较。我想你可以用这个 class Object def inst
UserInfo
的Ruby对象数组:
class UserInfo
attr_accessor :name, :title, :age
end
如何将这些数组合并到一个数组中?用户由其名称标识,因此我不希望有重复的名称。如果姓名、头衔、年龄等相等,我希望在新数组中有1个条目。如果名称相同,但任何其他细节不同,我可能希望位于不同阵列中的这两个用户手动修复错误
提前感谢一年前对象上的一种神秘的实例变量\u比较
。我想你可以用这个
class Object
def instance_variables_compare(o)
Hash[*self.instance_variables.map {|v|
self.instance_variable_get(v)!=o.instance_variable_get(v) ?
[v,o.instance_variable_get(v)] : []}.flatten]
end
end
一个俗气的例子
require 'Date'
class Cheese
attr_accessor :name, :weight, :expire_date
def initialize(name, weight, expire_date)
@name, @weight, @expire_date = name, weight, expire_date
end
end
stilton=Cheese.new('Stilton', 250, Date.parse("2010-12-02"))
gorgonzola=Cheese.new('Gorgonzola', 250, Date.parse("2010-12-17"))
>> stilton.instance_variables_compare(gorgonzola)
=> {"@name"=>"Gorgonzola", "@expire_date"=>#<Date: 4910305/2,0,2299161>}
>> gorgonzola.instance_variables_compare(stilton)
=> {"@name"=>"Stilton", "@expire_date"=>#<Date: 4910275/2,0,2299161>}
>> stilton.expire_date=gorgonzola.expire_date
=> #<Date: 4910305/2,0,2299161>
>> stilton.instance_variables_compare(gorgonzola)
=> {"@name"=>"Gorgonzola"}
>> stilton.instance_variables_compare(stilton)
=> {}
stilton2=Cheese.new('Stilton', 210, Date.parse("2010-12-02"))
gorgonzola2=Cheese.new('Gorgonzola', 250, Date.parse("2010-12-17"))
arr=[]<<stilton<<stilton2<<gorgonzola<<gorgonzola2
irb是我选择的武器
require 'Date'
class Cheese
attr_accessor :name, :weight, :expire_date
def initialize(name, weight, expire_date)
@name, @weight, @expire_date = name, weight, expire_date
end
end
stilton=Cheese.new('Stilton', 250, Date.parse("2010-12-02"))
gorgonzola=Cheese.new('Gorgonzola', 250, Date.parse("2010-12-17"))
>> stilton.instance_variables_compare(gorgonzola)
=> {"@name"=>"Gorgonzola", "@expire_date"=>#<Date: 4910305/2,0,2299161>}
>> gorgonzola.instance_variables_compare(stilton)
=> {"@name"=>"Stilton", "@expire_date"=>#<Date: 4910275/2,0,2299161>}
>> stilton.expire_date=gorgonzola.expire_date
=> #<Date: 4910305/2,0,2299161>
>> stilton.instance_variables_compare(gorgonzola)
=> {"@name"=>"Gorgonzola"}
>> stilton.instance_variables_compare(stilton)
=> {}
stilton2=Cheese.new('Stilton', 210, Date.parse("2010-12-02"))
gorgonzola2=Cheese.new('Gorgonzola', 250, Date.parse("2010-12-17"))
arr=[]<<stilton<<stilton2<<gorgonzola<<gorgonzola2
一个哈希值没有问题,一个哈希值有问题
h={}
problems=Hash.new([])
arr.each {|c|
if h.has_key?(c.name)
if problems.has_key?(c.name)
problems[c.name]=problems[c.name]<<c
elsif h[c.name].instance_variables_compare(c) != {}
problems[c.name]=problems[c.name]<<c<<h[c.name]
h.delete(c.name)
end
else
h[c.name]=c
end
}
据我所知,您根本不需要修改此代码来支持UserInfo
对象数组
直接比较属性或覆盖=
可能会快得多。这就是覆盖==
def ==(other)
return self.weight == other.weight && self.expire_date == other.expire_date
end
循环变成这个
arr.each {|c|
if h.has_key?(c.name)
if problems.has_key?(c.name)
problems[c.name]=problems[c.name]<<c
elsif h[c.name] != c
problems[c.name]=problems[c.name]<<c<<h[c.name]
h.delete(c.name)
end
else
h[c.name]=c
end
}
一年前,在对象上有一种神秘的实例变量\u compare
。我想你可以用这个
class Object
def instance_variables_compare(o)
Hash[*self.instance_variables.map {|v|
self.instance_variable_get(v)!=o.instance_variable_get(v) ?
[v,o.instance_variable_get(v)] : []}.flatten]
end
end
一个俗气的例子
require 'Date'
class Cheese
attr_accessor :name, :weight, :expire_date
def initialize(name, weight, expire_date)
@name, @weight, @expire_date = name, weight, expire_date
end
end
stilton=Cheese.new('Stilton', 250, Date.parse("2010-12-02"))
gorgonzola=Cheese.new('Gorgonzola', 250, Date.parse("2010-12-17"))
>> stilton.instance_variables_compare(gorgonzola)
=> {"@name"=>"Gorgonzola", "@expire_date"=>#<Date: 4910305/2,0,2299161>}
>> gorgonzola.instance_variables_compare(stilton)
=> {"@name"=>"Stilton", "@expire_date"=>#<Date: 4910275/2,0,2299161>}
>> stilton.expire_date=gorgonzola.expire_date
=> #<Date: 4910305/2,0,2299161>
>> stilton.instance_variables_compare(gorgonzola)
=> {"@name"=>"Gorgonzola"}
>> stilton.instance_variables_compare(stilton)
=> {}
stilton2=Cheese.new('Stilton', 210, Date.parse("2010-12-02"))
gorgonzola2=Cheese.new('Gorgonzola', 250, Date.parse("2010-12-17"))
arr=[]<<stilton<<stilton2<<gorgonzola<<gorgonzola2
irb是我选择的武器
require 'Date'
class Cheese
attr_accessor :name, :weight, :expire_date
def initialize(name, weight, expire_date)
@name, @weight, @expire_date = name, weight, expire_date
end
end
stilton=Cheese.new('Stilton', 250, Date.parse("2010-12-02"))
gorgonzola=Cheese.new('Gorgonzola', 250, Date.parse("2010-12-17"))
>> stilton.instance_variables_compare(gorgonzola)
=> {"@name"=>"Gorgonzola", "@expire_date"=>#<Date: 4910305/2,0,2299161>}
>> gorgonzola.instance_variables_compare(stilton)
=> {"@name"=>"Stilton", "@expire_date"=>#<Date: 4910275/2,0,2299161>}
>> stilton.expire_date=gorgonzola.expire_date
=> #<Date: 4910305/2,0,2299161>
>> stilton.instance_variables_compare(gorgonzola)
=> {"@name"=>"Gorgonzola"}
>> stilton.instance_variables_compare(stilton)
=> {}
stilton2=Cheese.new('Stilton', 210, Date.parse("2010-12-02"))
gorgonzola2=Cheese.new('Gorgonzola', 250, Date.parse("2010-12-17"))
arr=[]<<stilton<<stilton2<<gorgonzola<<gorgonzola2
一个哈希值没有问题,一个哈希值有问题
h={}
problems=Hash.new([])
arr.each {|c|
if h.has_key?(c.name)
if problems.has_key?(c.name)
problems[c.name]=problems[c.name]<<c
elsif h[c.name].instance_variables_compare(c) != {}
problems[c.name]=problems[c.name]<<c<<h[c.name]
h.delete(c.name)
end
else
h[c.name]=c
end
}
据我所知,您根本不需要修改此代码来支持UserInfo
对象数组
直接比较属性或覆盖=
可能会快得多。这就是覆盖==
def ==(other)
return self.weight == other.weight && self.expire_date == other.expire_date
end
循环变成这个
arr.each {|c|
if h.has_key?(c.name)
if problems.has_key?(c.name)
problems[c.name]=problems[c.name]<<c
elsif h[c.name] != c
problems[c.name]=problems[c.name]<<c<<h[c.name]
h.delete(c.name)
end
else
h[c.name]=c
end
}
这是另一种可能的方式。如果您有一种识别每个UserInfo的方法,请使用一个to_str方法打印出值:
def to_str()
return "#{@name}:#{@title}:#{@age}"
end
您可以使用inject和hash
all_users = a + b # collection of users to "merge"
res = all_users.inject({})do |h,v|
h[v.to_str] = v #save the value indexed on the string output
h # return h for the next iteration
end
merged = res.values #the unique users
这是另一种可能的方式。如果您有一种识别每个UserInfo的方法,请使用一个to_str方法打印出值:
def to_str()
return "#{@name}:#{@title}:#{@age}"
end
您可以使用inject和hash
all_users = a + b # collection of users to "merge"
res = all_users.inject({})do |h,v|
h[v.to_str] = v #save the value indexed on the string output
h # return h for the next iteration
end
merged = res.values #the unique users
在对象上重新定义相等比较,可以使用
然后,您可以按名称排序,并查找仅名称重复项
d = c.sort{ |p,q| p.name <=> q.name } #sort by name
name = ""
e = []
d.each do |item|
if item.name == name
e[-1] = [e[-1],item].flatten
else
e << item
end
end
d=c.sort{| p,q | p.name q.name}#按名称排序
name=“”
e=[]
d、 每个do |项目|
如果item.name==name
e[-1]=[e[-1],项].展平
其他的
e在对象上重新定义相等比较,您可以使用
然后,您可以按名称排序,并查找仅名称重复项
d = c.sort{ |p,q| p.name <=> q.name } #sort by name
name = ""
e = []
d.each do |item|
if item.name == name
e[-1] = [e[-1],item].flatten
else
e << item
end
end
d=c.sort{| p,q | p.name q.name}#按名称排序
name=“”
e=[]
d、 每个do |项目|
如果item.name==name
e[-1]=[e[-1],项].展平
其他的
e当你真正的意思是删除重复项时,你使用动词“合并”。另外,当您询问数组时,您已经用哈希
标记了它。您可能应该编辑这个问题以使其更清楚。@Olly:将标记从“hash”更改为“arrays”。当您真正的意思是删除重复项时,您可以使用动词merging。另外,当您询问数组时,您已经用哈希
标记了它。您可能应该编辑此问题以使其更清楚。@Olly:将标记从“hash”更改为“arrays”。它主要是从一篇旧博客文章中复制和粘贴的。另外,我刚刚纠正了一个错误。它主要是从一篇旧博客文章中复制和粘贴的。而且我刚刚纠正了一个错误。