基于特定位置元素唯一性的数组求和合并&x2B;ruby数组
我有一个二维数组,如下所示基于特定位置元素唯一性的数组求和合并&x2B;ruby数组,ruby,arrays,Ruby,Arrays,我有一个二维数组,如下所示 [[1, 4.0, "burger"], [1, 8.0, "tofu_log"], [2, 5.0, "burger"], [2, 6.5, "tofu_log"]] 在这里,每个元素都是餐厅id、价格和商品的集合。任务是返回唯一的餐厅id、价格总和和项目,使总和最小。我想去 [[1, 12.0, "burger, tofu_log"], [2, 11.5, "burger, tofu_log"]] 我做的如下 arr => [[1, 4.0, "bu
[[1, 4.0, "burger"], [1, 8.0, "tofu_log"], [2, 5.0, "burger"], [2, 6.5, "tofu_log"]]
在这里,每个元素都是餐厅id、价格和商品的集合。任务是返回唯一的餐厅id、价格总和和项目,使总和最小。我想去
[[1, 12.0, "burger, tofu_log"], [2, 11.5, "burger, tofu_log"]]
我做的如下
arr
=> [[1, 4.0, "burger"], [1, 8.0, "tofu_log"], [2, 5.0, "burger"], [2, 6.5, "tofu_log"]]
ids = arr.map{|i| i[0]}.uniq
=> [1, 2]
a = ids.map{|id| arr.map{|i| i if i[0] == id }.compact}
=> [[[1, 4.0, "burger"], [1, 8.0, "tofu_log"]], [[2, 5.0, "burger"], [2, 6.5, "tofu_log"]]]
a.map{|x| [x[0][0], x.map{|y| y[1]}.inject(:+), x.map{|i| i[2..-1]}.join(', ')] }.sort{|x| x[1]}.first
=> [2, 11.5, "burger, tofu_log"]
有没有不那么复杂的方法呢?这里有一种方法 代码
def doit(arr)
arr.each_with_object({}) { |(id,price,item),h| h.update({id=>[price,[item]]}) \
{|_,(o_price,o_item), (n_price,n_item)|[o_price+n_price, o_item+n_item]}}
.map { |id, (tot_price,*items)| [id, tot_price, items].flatten }
.sort_by { |_,tot_price| tot_price }
end
arr = [[1, 4.0, "burger"], [1, 8.0, "tofu_log"],
[2, 5.0, "burger"], [2, 6.5, "tofu_log"]]
doit(arr)
#=> [[2, 11.5, "burger", "tofu_log"], [1, 12.0, "burger", "tofu_log"]]
这是按总价排序的,从最低到最高。如果您想按从高到低的顺序进行排序,如您的示例中所示,请将排序标准tot_price
替换为-tot_price
,或将排序标准.reverse
替换到最后
示例
def doit(arr)
arr.each_with_object({}) { |(id,price,item),h| h.update({id=>[price,[item]]}) \
{|_,(o_price,o_item), (n_price,n_item)|[o_price+n_price, o_item+n_item]}}
.map { |id, (tot_price,*items)| [id, tot_price, items].flatten }
.sort_by { |_,tot_price| tot_price }
end
arr = [[1, 4.0, "burger"], [1, 8.0, "tofu_log"],
[2, 5.0, "burger"], [2, 6.5, "tofu_log"]]
doit(arr)
#=> [[2, 11.5, "burger", "tofu_log"], [1, 12.0, "burger", "tofu_log"]]
解释
让我们用上面的例子一行一行地看一下
arr.each_with_object({}) { |(id,price,item),h|...}
这里创建一个空哈希(“对象”)并将arr
的每个元素传递给块。第一个元素是[1,4.0,“burger”]
,它将以下值分配给块变量:
id #=> 1
price #=> 4.0
item #=> "burger"
h #=> {}
如果在id,price,item
Ruby周围没有括号,它会引发一个异常,因为它只需要两个参数:元素(数组)arr
和由each\u和\u object
创建的哈希。括号告诉Ruby,我们正在将arr
的元素消歧为其三个组成部分
我们现在使用(akamerge!
)将从arr
的第一个元素形成的哈希合并到当前为空的哈希h
。我们正在合并的哈希是
{id=>[price,[item]]} #=> {1=>[4.0,["burger"]]}
因为h
没有键1
,所以这个散列被合并,所以现在
h #=> {1=>[4.0,["burger"]]}
arr
的下一个元素是[1,8.0,“豆腐日志”]
,因此块变量被赋值
id #=> 1
price #=> 8.0
item #=> "tofu_log" (yuk!)
h #=> {1=>[4.0,["burger"]]}
我们现在尝试合并散列
{id=>[price,[item]]} #=> {1=>[8.0,["tofu_log"]]}
但是由于散列h
已经具有键1
,update
的块
{|k,(o_price,o_item), (n_price,n_item)| [o_price + n_price, o_item + n_item]}
用于确定键1
(块存在的理由)的合并值
此块具有以下值:
{|1,(4.0,["burger"]), (8.0,["tofu_log"])| [4.0 + 8.0, ["burger"]+["tofu_log"|}
第一个块变量是键,它等于1
,但由于我们没有使用它,我用下划线(占位符)替换了它,以强调它没有被使用。第二个块变量(“旧值”)是合并哈希中1
的值,第三个值(“新值”)是我们正在合并的哈希中1
的值
因此,键1
的合并值变为
[12.0, ["burger, "tofu_log"]]
所以散列现在是
h => { 1=>[12.0, ["burger, "tofu_log"]] }
将arr
的其余两个元素传递到块后,每个带有\u对象的\u
返回哈希值
h => {1=>[12.0, ["burger", "tofu_log"]], 2=>[11.5, ["burger", "tofu_log"]]}
然后使用将哈希转换为所需格式的数组
对于h
的第一个元素,块变量为
id => 1
items => [12.0, ["burger, "tofu_log"]]
我们申请:
最后一个操作是排序,但我不确定要排序的是什么,所以我不会讨论这个问题。这里有一种方法
arr.group_by { |rest_id, _| rest_id }.map do |rest_id, items|
[rest_id,
items.map { |_, price| price }.inject(:+),
items.sort.map { |_, _, product| product }.join(", ") ]
end
# => [[1, 12.0, "burger, tofu_log"], [2, 11.5, "burger, tofu_log"]]
代码
def doit(arr)
arr.each_with_object({}) { |(id,price,item),h| h.update({id=>[price,[item]]}) \
{|_,(o_price,o_item), (n_price,n_item)|[o_price+n_price, o_item+n_item]}}
.map { |id, (tot_price,*items)| [id, tot_price, items].flatten }
.sort_by { |_,tot_price| tot_price }
end
arr = [[1, 4.0, "burger"], [1, 8.0, "tofu_log"],
[2, 5.0, "burger"], [2, 6.5, "tofu_log"]]
doit(arr)
#=> [[2, 11.5, "burger", "tofu_log"], [1, 12.0, "burger", "tofu_log"]]
这将按照从最低到最高的总价格进行排序。如果您想从最高到最低进行排序,如您的示例中所示,请将排序标准tot_price
替换为-tot_price
,或将反转到最末端
示例
def doit(arr)
arr.each_with_object({}) { |(id,price,item),h| h.update({id=>[price,[item]]}) \
{|_,(o_price,o_item), (n_price,n_item)|[o_price+n_price, o_item+n_item]}}
.map { |id, (tot_price,*items)| [id, tot_price, items].flatten }
.sort_by { |_,tot_price| tot_price }
end
arr = [[1, 4.0, "burger"], [1, 8.0, "tofu_log"],
[2, 5.0, "burger"], [2, 6.5, "tofu_log"]]
doit(arr)
#=> [[2, 11.5, "burger", "tofu_log"], [1, 12.0, "burger", "tofu_log"]]
解释
让我们用上面的例子一行一行地看一下
arr.each_with_object({}) { |(id,price,item),h|...}
这里创建一个空散列(“对象”),并将arr
的每个元素传递给块。第一个是[1,4.0,“burger”]
,它将以下值分配给块变量:
id #=> 1
price #=> 4.0
item #=> "burger"
h #=> {}
如果在id、price、item
周围没有括号,Ruby将引发一个异常,因为它只需要两个参数:arr
的元素(数组)和每个带有\u对象的\u创建的散列。括号告诉Ruby,我们正在将arr
的元素消歧为它的三个组成部分
我们现在使用(akamerge!
)将从arr
的第一个元素形成的哈希合并到当前为空的哈希h
。我们正在合并的哈希是
{id=>[price,[item]]} #=> {1=>[4.0,["burger"]]}
因为h
没有键1
,所以这个散列被合并,所以现在
h #=> {1=>[4.0,["burger"]]}
arr
的下一个元素是[1,8.0,“豆腐日志”]
,因此块变量被赋值
id #=> 1
price #=> 8.0
item #=> "tofu_log" (yuk!)
h #=> {1=>[4.0,["burger"]]}
我们现在尝试合并散列
{id=>[price,[item]]} #=> {1=>[8.0,["tofu_log"]]}
但是由于散列h
已经具有键1
,update
的块
{|k,(o_price,o_item), (n_price,n_item)| [o_price + n_price, o_item + n_item]}
用于确定键1
(块存在的理由)的合并值
此块具有以下值:
{|1,(4.0,["burger"]), (8.0,["tofu_log"])| [4.0 + 8.0, ["burger"]+["tofu_log"|}
第一个块变量是键,它等于1
,但由于我们没有使用它,我用下划线(占位符)替换它,以强调它没有被使用。第二个块变量(“旧值”)是合并哈希中1
的值,第三个值(“新值”)是我们正在合并的哈希中1
的值
因此,键1
的合并值变为
[12.0, ["burger, "tofu_log"]]
所以散列现在是
h => { 1=>[12.0, ["burger, "tofu_log"]] }
将arr
的其余两个元素传递到块后,每个带有\u对象的\u
返回哈希值
h => {1=>[12.0, ["burger", "tofu_log"]], 2=>[11.5, ["burger", "tofu_log"]]}
然后使用将哈希转换为所需格式的数组
对于h
的第一个元素,块变量为
id => 1
items => [12.0, ["burger, "tofu_log"]]
我们申请:
最后一个操作是排序,但我不确定要排序的是什么,因此我不会讨论这个问题。您的操作是正确的。。因为我没有注意到排序的事实+1很好地使用了group\u by
,Uri。考虑做一些消歧以便更好的可读性。例如:arr.group_by{id,{id}
,items.inject(0){tot,({,price){tot+price}
,items.sort.map{124; uu,{uu,product}
。第二个建议也简化了一点
arr.group_by { |rest_id, _| rest_id }.map do |rest_id, items|
[rest_id,
items.map { |_, price| price }.inject(:+),
items.sort.map { |_, _, product| product }.join(", ") ]
end
# => [[1, 12.0, "burger, tofu_log"], [2, 11.5, "burger, tofu_log"]]