如何组合具有公共元素的数组元素?

时间:2013-12-03 05:07:44

标签: ruby arrays

我想要一组数字对:

[[2, 3], [2, 15], [3, 15], [7, 8], [8, 7], [11, 15]] 

如果其中两个数字对有一个共同的数字,将它们组合起来并显示唯一值,最终创建这个数组:

[[2, 3, 15, 11], [7, 8]]

输出数组中的数字顺序并不重要。什么是最好的解决方案?

4 个答案:

答案 0 :(得分:3)

在霍华德的评论之后,答案得到了纠正。

[[2, 3], [2, 15], [3, 2], [3, 15], [7, 8], [8, 7], [11, 15], [15, 2], [15, 3], [15, 11]]
.each_with_object([]) do |e1, a|
  a.select{|e2| (e1 & e2).any?}.each{|e2| e1.concat(a.delete(e2))}
  e1.uniq!
  a.push(e1)
end
# => [[8, 7], [15, 11, 3, 2]]

答案 1 :(得分:1)

这只是另一个映射和排序问题,:

array = [[2, 3], [2, 15], [3, 2], [3, 15], [7, 8], [8, 7], [11, 15], [15, 2], [15, 3], [15, 11]]
array.map{|a| array.each{|x| a |= x if (x & a).any?}; a.sort}.uniq
#=> [[2, 3, 11, 15], [7, 8]]

答案 2 :(得分:0)

不像@ sawa的解决方案那么优雅 - 但适用于所有情况:

def includes? item, groups
  groups.each{|sub|
    return true if sub.include?(item)
  }
  false
end

def add groups, match, item
  groups.each{|sub|
    if sub.include?(match)
      sub << item
      sub.uniq!
      return
    end
  }
end

def iterate arr  
  groups = []
  grp = []
      arr.each do |a,b|
        grp = [a,b] if grp.empty?
        if includes? a, groups
          add groups, a, b
        elsif includes? b, groups
          add groups, b, a
        else
          groups << [a,b]
        end
      end
  groups
end

arr = [[2, 3], [2, 15], [3, 2], [3, 15], [7, 8], [8, 7], [11, 15], [15, 2], [15, 3], [15, 11]]
p iterate(arr)

<强>输出

[[2, 3, 15, 11], [7, 8]]

答案 3 :(得分:0)

递归解决方案:

def doit(a,b)
  return a unless b
  h = b.group_by {|e| (a[-1] & e).any?}
  h[true] ? a[-1] |= h[true].flatten : a << h[false].pop
  doit(a, h[false])
end

arr = [[2, 3], [2, 15], [3, 2], [3, 15], [16, 21], [7, 8], [8, 7], \
       [21, 44], [11, 15], [15, 2], [15, 3], [15, 11], [8, 9]]
doit([arr.pop], arr) # => [[8, 9, 7], [15, 11, 2, 3], [21, 44, 16]]