Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails-如何在单独的对象中一起添加值_Ruby On Rails_Ruby - Fatal编程技术网

Ruby on rails Rails-如何在单独的对象中一起添加值

Ruby on rails Rails-如何在单独的对象中一起添加值,ruby-on-rails,ruby,Ruby On Rails,Ruby,您有一个包含键值引用的对象数组 [{booking_ref: 'w578383', foo: 'bar', price1: 500, price2: 30], {booking_ref: 'w578383', foo: 'bar', price1: 600, price2: 40}, {booking_ref: 'r123523', foo: 'bar', price1: 699, price2: 4}] 我想: 按键值参考对对象进行分组(预订参考) 通过这些分组,只将财务价值加在一起(pr

您有一个包含键值引用的对象数组

[{booking_ref: 'w578383', foo: 'bar', price1: 500, price2: 30],
{booking_ref: 'w578383', foo: 'bar', price1: 600, price2: 40},
{booking_ref: 'r123523', foo: 'bar', price1: 699, price2: 4}]
我想:

  • 按键值参考对对象进行分组(预订参考)
  • 通过这些分组,只将财务价值加在一起(price1和price2加在另一个预订的price1和price2上)
  • 将分组折叠回包含键值引用的对象数组。这将是:

    [{booking_ref: 'w578383', foo: 'bar', price1: 1100, price2: 70},
    {booking_ref: 'r123523', foo: 'bar', price1: 699, price2: 4}]
    
我在想:

objects.group_by(&:booking_ref).each {|group|
  group.merge {|key, value1, value2| value1 + value2 if key == price1 || price2}
}

这样做有效吗?如果有效,那么如何按状态将它们从组中返回?

使用散列对象,您可以计算总和并将它们合并回每个组中的第一个散列:

bookings = [
{booking_ref: 'w578383', foo: 'bar', price1: 500, price2: 30},
{booking_ref: 'w578383', foo: 'bar', price1: 600, price2: 40},
{booking_ref: 'r123523', foo: 'bar', price1: 699, price2: 4}
]

grouped_bookings = bookings.group_by{ |h| h[:booking_ref] }.map do |ref, hs|
  sums = hs.each_with_object(Hash.new(0)) do |h, sum|
    %i(price1 price2).each do |price|
      sum[price] += h[price].to_i
    end
  end
  hs.first.merge(sums)
end

p grouped_bookings
# [{:booking_ref=>"w578383", :foo=>"bar", :price1=>1100, :price2=>70},
# {:booking_ref=>"r123523", :foo=>"bar", :price1=>699, :price2=>4}]

使用散列对象,您可以计算总和并将其合并回每个组中的第一个散列:

bookings = [
{booking_ref: 'w578383', foo: 'bar', price1: 500, price2: 30},
{booking_ref: 'w578383', foo: 'bar', price1: 600, price2: 40},
{booking_ref: 'r123523', foo: 'bar', price1: 699, price2: 4}
]

grouped_bookings = bookings.group_by{ |h| h[:booking_ref] }.map do |ref, hs|
  sums = hs.each_with_object(Hash.new(0)) do |h, sum|
    %i(price1 price2).each do |price|
      sum[price] += h[price].to_i
    end
  end
  hs.first.merge(sums)
end

p grouped_bookings
# [{:booking_ref=>"w578383", :foo=>"bar", :price1=>1100, :price2=>70},
# {:booking_ref=>"r123523", :foo=>"bar", :price1=>699, :price2=>4}]

首先,
groupby
可以,然后使用
map
迭代散列,然后使用
inject
将列表中的值减少为总和

objects.group_by(&:booking_ref)
       .map{|ref, list| {booking_ref: ref, 
                        price1:  => list.inject(0){|sum,h| sum + h.price1},
                        price2: => list.inject(0){|sum,h| sum + h.price2}
                        }
           }

首先,
groupby
可以,然后使用
map
迭代散列,然后使用
inject
将列表中的值减少为总和

objects.group_by(&:booking_ref)
       .map{|ref, list| {booking_ref: ref, 
                        price1:  => list.inject(0){|sum,h| sum + h.price1},
                        price2: => list.inject(0){|sum,h| sum + h.price2}
                        }
           }

在这里采用面向对象的方法,您可以使它看起来非常整洁和优雅。关键是在对象上定义
+
方法。完整示例如下:

class Booking
  attr_accessor :booking_ref, :foo, :price1, :price2

  def initialize(params={})
    params.each { |key, value| send "#{key}=", value }
  end

  # add up prices, and return new Booking object
  def +(other)
    new_obj = self.dup
    new_obj.price1 += other.price1
    new_obj.price2 += other.price2
    new_obj
  end
end

# set up example bookings
bookings = [
  Booking.new(booking_ref: 'w578383', foo: 'bar', price1: 500, price2: 30),
  Booking.new(booking_ref: 'w578383', foo: 'bar', price1: 600, price2: 40),
  Booking.new(booking_ref: 'r123523', foo: 'bar', price1: 699, price2: 4)
]


# grouping becomes very simple - potentially a one-liner
bookings.group_by(&:booking_ref).map { |_, values| values.reduce(&:+) }
# => [
        #<Booking:... @booking_ref="w578383", @foo="bar", @price1=1100, @price2=70>,
        #<Booking:... @booking_ref="r123523", @foo="bar", @price1=699, @price2=4>
     ]
订舱
属性访问者:预订参考号:foo,:price 1,:price 2
def初始化(参数={})
params.each{key,value | send“#{key}=”,value}
结束
#累计价格,并返回新的预订对象
def+(其他)
new_obj=self.dup
新对象价格1+=其他价格1
新对象价格2+=其他价格2
新_obj
结束
结束
#建立示例预订
预订=[
新预订(预订参考:w578383,foo:bar,价格1:500,价格2:30),
新预订(预订编号:w578383,foo:bar,价格1:600,价格2:40),
预订。新(预订参考:r123523,富:酒吧,价格1:699,价格2:4)
]
#分组变得非常简单-可能是一行
bookings.group_by(&:booking_ref).map{| |,values | values.reduce(&:+)}
# => [
#,
#
]

在这里采用面向对象的方法,您可以使它看起来非常整洁和优雅。关键是在对象上定义
+
方法。完整示例如下:

class Booking
  attr_accessor :booking_ref, :foo, :price1, :price2

  def initialize(params={})
    params.each { |key, value| send "#{key}=", value }
  end

  # add up prices, and return new Booking object
  def +(other)
    new_obj = self.dup
    new_obj.price1 += other.price1
    new_obj.price2 += other.price2
    new_obj
  end
end

# set up example bookings
bookings = [
  Booking.new(booking_ref: 'w578383', foo: 'bar', price1: 500, price2: 30),
  Booking.new(booking_ref: 'w578383', foo: 'bar', price1: 600, price2: 40),
  Booking.new(booking_ref: 'r123523', foo: 'bar', price1: 699, price2: 4)
]


# grouping becomes very simple - potentially a one-liner
bookings.group_by(&:booking_ref).map { |_, values| values.reduce(&:+) }
# => [
        #<Booking:... @booking_ref="w578383", @foo="bar", @price1=1100, @price2=70>,
        #<Booking:... @booking_ref="r123523", @foo="bar", @price1=699, @price2=4>
     ]
订舱
属性访问者:预订参考号:foo,:price 1,:price 2
def初始化(参数={})
params.each{key,value | send“#{key}=”,value}
结束
#累计价格,并返回新的预订对象
def+(其他)
new_obj=self.dup
新对象价格1+=其他价格1
新对象价格2+=其他价格2
新_obj
结束
结束
#建立示例预订
预订=[
新预订(预订参考:w578383,foo:bar,价格1:500,价格2:30),
新预订(预订编号:w578383,foo:bar,价格1:600,价格2:40),
预订。新(预订参考:r123523,富:酒吧,价格1:699,价格2:4)
]
#分组变得非常简单-可能是一行
bookings.group_by(&:booking_ref).map{| |,values | values.reduce(&:+)}
# => [
#,
#
]
只要您可以使用,就可以使用某种形式的or(也称为
合并!
),反之亦然。其他人使用了
groupby
,所以这里有一个哈希合并答案

让变量
bookings
等于散列数组,可以编写以下代码

keys_to_aggregate = [:price1, :price2]

bookings.each_with_object({}) { |g,h| h.update(g[:booking_ref]=>g) { |_,o,n|
  keys_to_aggregate.reduce(o) { |f,k| f.merge(k=>o[k] + n[k]) } } }.values
  #=> [{:booking_ref=>"w578383", :foo=>"bar", :price1=>1100, :price2=>70},
  #    {:booking_ref=>"r123523", :foo=>"bar", :price1=>699, :price2=>4}] 
bookings.each_with_object({}) { |g,h| h.update(g[:booking_ref]=>g) { |_,o,n|
  keys_to_aggregate.reduce(o) { |f,k| f.merge(k=>o[k] + n[k]) } } }
  #=> {"w578383"=>{:booking_ref=>"w578383", :foo=>"bar", :price1=>1100, :price2=>70},
  #    "r123523"=>{:booking_ref=>"r123523", :foo=>"bar", :price1=>699, :price2=>4}}
请注意,在计算表达式末尾之前,我们有以下内容

keys_to_aggregate = [:price1, :price2]

bookings.each_with_object({}) { |g,h| h.update(g[:booking_ref]=>g) { |_,o,n|
  keys_to_aggregate.reduce(o) { |f,k| f.merge(k=>o[k] + n[k]) } } }.values
  #=> [{:booking_ref=>"w578383", :foo=>"bar", :price1=>1100, :price2=>70},
  #    {:booking_ref=>"r123523", :foo=>"bar", :price1=>699, :price2=>4}] 
bookings.each_with_object({}) { |g,h| h.update(g[:booking_ref]=>g) { |_,o,n|
  keys_to_aggregate.reduce(o) { |f,k| f.merge(k=>o[k] + n[k]) } } }
  #=> {"w578383"=>{:booking_ref=>"w578383", :foo=>"bar", :price1=>1100, :price2=>70},
  #    "r123523"=>{:booking_ref=>"r123523", :foo=>"bar", :price1=>699, :price2=>4}}
这使用了
Hash#update
的形式,它使用一个块来确定合并的两个哈希中存在的键的值。有关详细信息,请参阅文档,特别是值确定块的三个变量(
k
o
n
)的定义。(我用
\uu
代替
k
[键]表示它不用于块计算。)

只要可以使用,就可以使用某种形式的or(也称为
合并!
),反之亦然。其他人使用了
groupby
,所以这里有一个哈希合并答案

让变量
bookings
等于散列数组,可以编写以下代码

keys_to_aggregate = [:price1, :price2]

bookings.each_with_object({}) { |g,h| h.update(g[:booking_ref]=>g) { |_,o,n|
  keys_to_aggregate.reduce(o) { |f,k| f.merge(k=>o[k] + n[k]) } } }.values
  #=> [{:booking_ref=>"w578383", :foo=>"bar", :price1=>1100, :price2=>70},
  #    {:booking_ref=>"r123523", :foo=>"bar", :price1=>699, :price2=>4}] 
bookings.each_with_object({}) { |g,h| h.update(g[:booking_ref]=>g) { |_,o,n|
  keys_to_aggregate.reduce(o) { |f,k| f.merge(k=>o[k] + n[k]) } } }
  #=> {"w578383"=>{:booking_ref=>"w578383", :foo=>"bar", :price1=>1100, :price2=>70},
  #    "r123523"=>{:booking_ref=>"r123523", :foo=>"bar", :price1=>699, :price2=>4}}
请注意,在计算表达式末尾之前,我们有以下内容

keys_to_aggregate = [:price1, :price2]

bookings.each_with_object({}) { |g,h| h.update(g[:booking_ref]=>g) { |_,o,n|
  keys_to_aggregate.reduce(o) { |f,k| f.merge(k=>o[k] + n[k]) } } }.values
  #=> [{:booking_ref=>"w578383", :foo=>"bar", :price1=>1100, :price2=>70},
  #    {:booking_ref=>"r123523", :foo=>"bar", :price1=>699, :price2=>4}] 
bookings.each_with_object({}) { |g,h| h.update(g[:booking_ref]=>g) { |_,o,n|
  keys_to_aggregate.reduce(o) { |f,k| f.merge(k=>o[k] + n[k]) } } }
  #=> {"w578383"=>{:booking_ref=>"w578383", :foo=>"bar", :price1=>1100, :price2=>70},
  #    "r123523"=>{:booking_ref=>"r123523", :foo=>"bar", :price1=>699, :price2=>4}}

这使用了
Hash#update
的形式,它使用一个块来确定合并的两个哈希中存在的键的值。有关详细信息,请参阅文档,特别是值确定块的三个变量(
k
o
n
)的定义。(我用
\uu
代替
k
[键]表示它不用于块计算。)

@JamesJY:是的,我的对象是散列,你的可能不是。因为没有包含任何对象定义,所以我不得不使用哈希。你可以用
对象替换
散列[:key]
调用。key
方法调用。@JamesJY:请用代码更新你的问题以初始化你的对象。这些对象是什么还不清楚。它们看起来像散列,但显然不是。他们的类别是什么?@JamesJY:是的,我的对象是散列,你的可能不是。因为没有包含任何对象定义,所以我不得不使用哈希。你可以用
对象替换
散列[:key]
调用。key
方法调用。@JamesJY:请用代码更新你的问题以初始化你的对象。这些对象是什么还不清楚。它们看起来像散列,但显然不是。他们的课程是什么?很有效谢谢!有一件事是,有一种方法可以重构它,使它不必在一长串中列出每个价格。事实上,有5/6的价格需要合并。我修改了方法来解决这个问题。@JamesJY:如果这段代码适合您的数据结构,我真的不明白为什么它不适合我的代码。不管怎样,你通常不会对卡里的答案有错误。这很有效,谢谢!有一件事是有一种方法可以重构它,而不必在一个目录中列出每个价格