我有一组像这样的数组:
[["1","2"],["1","3"],["2","3"],["2","5"]]
我想找到像
这样的第一个值的并集 ["1","2"],["1","3"]
匹配,因此我需要创建像["1","2,3"]
所以生成的数组就像
[["1","2,3"],["2","3,5"]]
答案 0 :(得分:4)
与Ruby中的大多数问题一样,Enumerable模块完成了这项工作:
input = [["1","2"],["1","3"],["2","3"],["2","5"]]
result = input.group_by do |item|
# Group by first element
item[0]
end.collect do |key, items|
# Compose into new format
[
key,
items.collect do |item|
item[1]
end.join(',')
]
end
puts result.inspect
# => [["1", "2,3"], ["2", "3,5"]]
汇总类似的内容时,group_by
方法非常方便,collect
非常适合重写元素的显示方式。
答案 1 :(得分:2)
你所要求的并不是每个2的真正联盟的真正联盟:
data = [["1","2"],["1","3"],["2","3"],["2","5"]]
data.each_slice(2).map{|a,b| a | b.to_a }
#=> [["1","2","3"],["2","3","5"]]
这是一个非常简单的解决方案,可以根据您的需求修改此概念:
data = [["1","2"],["1","3"],["2","3"],["2","5"]]
data.each_slice(2).map do |a,b|
unified = (a | b.to_a)
[unified.shift,unified.join(',')]
end
#=> [["1", "2,3"], ["2", "3,5"]]
如果阵列数量不均匀,则将to_a
添加到管道变量b
。例如
data = [["1","2"],["1","3"],["2","3"],["2","5"],["4","7"]]
data.each_slice(2).map do |a,b|
unified = (a | b.to_a)
[unified.shift,unified.join(',')]
end
#=> [["1", "2,3"], ["2", "3,5"], ["4","7"]]
如果你的意思是你希望这种情况发生而不管订单如何,那么这将有效但会破坏data
对象
data.group_by(&:shift).map{|k,v| [k,v.flatten.join(',')]}
#=> [["1", "2,3"], ["2", "3,5"], ["4","7"]]
非破坏性地你可以打电话
data.map(&:dup).group_by(&:shift).map{|k,v| [k,v.flatten.join(',')]}
#=> [["1", "2,3"], ["2", "3,5"], ["4","7"]]
答案 2 :(得分:1)
这是另一种方式。
<强>代码强>
def doit(arr)
arr.each_with_object({}) { |(i,*rest),h| (h[i] ||= []).concat(rest) }
.map { |i,rest| [i, rest.join(',')] }
end
<强>实施例强>
arr1 = [["1","2"],["1","3"],["2","3"],["2","5"]]
doit(arr1)
#=> [["1", "2,3"], ["2", "3,5"]]
arr2 = [["1","2","6"],["2","7"],["1","3"],["2","3","9","4","cat"]]
doit(arr2)
# => [["1", "2,6,3"], ["2", "7,3,9,4,cat"]]
<强>解释强>
对于上面的arr1
,我们获得:
enum = arr1.each_with_object({})
#=> #<Enumerator: [["1", "2"], ["1", "3"], ["2", "3"],
# ["2", "5"]]:each_with_object({})>
我们可以将enum
转换为数组,查看其元素:
enum.to_a
#=> [[["1", "2"], {}], [["1", "3"], {}],
# [["2", "3"], {}], [["2", "5"], {}]]
这些元素将被传递到块中,并由Enumerator#each分配给块变量,它将调用Array#each。可以通过在[["1", "2"], {}]
上调用Enumerator#next来获取这些元素中的第一个(enum
):
(i,*rest),h = enum.next
#=> [["1", "2"], {}]
i #=> "1"
rest #=> ["2"]
h #=> {}
然后我们执行:
(h[i] ||= []).concat(rest)
#=> (h["1"] ||= []).concat(["2"])
#=> (nil ||= []).concat(["2"])
#=> [].concat(["2"])
#=> ["2"]
each
然后将enum
的下一个元素传递给块:
(i,*rest),h = enum.next
#=> [["1", "3"], {"1"=>["2"]}]
i #=> "1"
rest #=> ["3"]
h #=> {"1"=>["2"]}
(h[i] ||= []).concat(rest)
#=> (h["1"] ||= []).concat(["3"])
#=> (["2"] ||= []).concat(["3"])
#=> ["2"].concat(["3"])
#=> ["2", "3"]
将enum
的最后两个元素传递给块后,我们得到:
h=> {"1"=>["2", "3"], "2"=>["3", "5"]}
map
创建一个枚举器:
enum_h = h.each
#=> > #<Enumerator: {"1"=>["2", "3"]}:each>
并调用Enumerator#each
(调用Hash#each)将enum_h
的每个元素传递到块中:
i, rest = enum_h.next
#=> ["1", ["2", "3"]]
然后计算:
[i, rest.join(',')]
#=> ["1", ["2", "3"].join(',')]
#=> ["1", "2,3"]
enum_h
的其他元素的处理方式相似。