ruby - Ruby,删除超级数组
问题描述
如果我有一个数组数组A
,并且想要摆脱在A
其中也有一个子数组的所有数组A
,我该怎么做。在这种情况下,array_1
是array_2
if的子数组array_1 - array_2 = []
。在多个数组只是相同元素的重新排列版本的情况下,如果您可以摆脱除其中一个之外的所有数组,则可以加分,但如果更容易,您可以随心所欲地处理它。
在 python 中,我可以很容易地使用理解,A
作为一组冻结集:
A = {a for a in A if all(b-a for b in A-{a})}
有没有一种简单的方法可以用红宝石写这个?我不在乎是否A
保留了数组的顺序。此外,在我的程序中,没有一个数组有重复的元素,如果这让事情变得更容易/更快的话。
例子
A = [[1,6],[1,2],[2,4],[3,5],[1,3,6],[2,3,6]]
# [1,6] is a subarray of [1,3,6], so [1,3,6] should be removed
remove_super_arrays(A)
> A = [[1,6],[1,2],[2,4],[3,5],[2,3,6]]
A = [[1,2,4],[2,3,4],[1,4,5],[2,6]]
# although there is overlap, there are no subarrays, so nothing should be removed
remove_super_arrays(A)
> A = [[1,2,4],[2,3,4],[1,4,5],[2,6]]
A = [[1],[2,1,3],[2,4],[1,4]]
# [1] is a subarray of [2,1,3] and [1,4]
remove_super_arrays(A)
> A = [[1],[2,4]]
解决方案
代码
def remove_super_arrays(arr)
order = arr.each_with_index.to_a.to_h
arr.sort_by(&:size).reject.with_index do |a,i|
arr[0,i].any? { |aa| (aa.size < a.size) && (aa-a).empty? }
end.sort_by { |a| order[a] }
end
例子
remove_super_arrays([[1,6],[1,2],[2,4],[3,5],[1,3,6],[2,3,6]] )
#=> [[1,6],[1,2],[2,4],[3,5],[2,3,6]]
remove_super_arrays([[1,2,4],[2,3,4],[1,4,5],[2,6]])
#=> [[1,2,4],[2,3,4],[1,4,5],[2,6]]
remove_super_arrays([[1],[2,1,3],[2,4],[1,4]])
#=> [[1],[2,4]]
解释
考虑第一个例子。
arr = [[1,6],[1,2],[2,4],[3,5],[1,3,6],[2,3,6]]
我们首先保存元素的位置a
order = arr.each_with_index.to_a.to_h # save original order
#=> {[1, 6]=>0, [1, 2]=>1, [2, 4]=>2, [3, 5]=>3, [1, 3, 6]=>4, [2, 3, 6]=>5}
然后拒绝 的元素arr
:
b = arr.sort_by(&:size)
#=> [[1, 6], [1, 2], [2, 4], [3, 5], [1, 3, 6], [2, 3, 6]]
c = b.reject.with_index do |a,i|
arr[0,i].any? { |aa| (aa.size < a.size) && (aa-a).empty? }
end
#=> [[1, 6], [1, 2], [2, 4], [3, 5], [2, 3, 6]]
最后,重新排序c
以对应 的元素的原始排序arr
。
c.sort_by { |a| order[a] }
#=> [[1, 6], [1, 2], [2, 4], [3, 5], [2, 3, 6]]
在这种情况下,它恰好与 的元素具有相同的顺序c
。
让我们更仔细地看一下 的计算c
:
enum1 = b.reject
#=> #<Enumerator: [[1, 6], [1, 2], [2, 4], [3, 5], [1, 3, 6],
# [2, 3, 6]]:reject>
enum2 = enum1.with_index
#=> #<Enumerator: #<Enumerator: [[1, 6], [1, 2], [2, 4], [3, 5],
# [1, 3, 6], [2, 3, 6]]:reject>:with_index>
第一个元素由枚举器生成enum2
并传递给块并分配为块变量的值:
a, i = enum2.next
#=> [[1, 6], 0]
a #=> [1, 6]
i #=> 0
然后执行块计算:
d = arr[0,i]
#=> []
d.any? { |aa| (aa.size < a.size) && (aa-a).empty? }
#=> false
所以a[0]
不被拒绝。传递给块的下一对enum2
是[[1, 2], 1]
。该值也被保留,但让我们跳到传递给块的最后一个元素enum2
:
a, i = enum2.next
#=> [[1, 2], 1]
a, i = enum2.next
#=> [[2, 4], 2]
a, i = enum2.next
#=> [[3, 5], 3]
a, i = enum2.next
#=> [[1, 3, 6], 4]
a #=> [1, 3, 6]
i #=> 4
执行块计算:
d = arr[0,i]
#=> [[1, 6], [1, 2], [2, 4], [3, 5]]
d.any? { |aa| (aa.size < a.size) && (aa-a).empty? }
#=> true
true
被退回,a
被拒绝。在最后一个计算中,第一个元素d
被传递给块并执行以下计算:
aa = [1, 6]
(aa.size < a.size)
#=> 2 < 3 => true
(aa-a).empty?
#=> ([1, 6] - [1, 3, 6]).empty? => [].empty? => true
由于true && true #=> true
, a
( [1, 3, 6]
) 被拒绝。
替代计算
以下是与 OP 的 Python 等效项更接近的匹配,但效率较低:
def remove_super_arrays(arr)
arr.select do |a|
(arr-[a]).all? { |aa| aa.size > a.size || (aa-a).any? }
end
end
或者
def remove_super_arrays(arr)
arr.reject do |a|
(arr-[a]).any? { |aa| (aa.size < a.size) && (aa-a).empty? }
end
end
推荐阅读
- project-reactor - project-reactor 中的 RxJava PublishSubject 等价于什么?
- c# - C# 软数字与输入的差异
- java - 检测矩阵中的相邻元素(SameGame)
- tensorflow - 在 Tensorflow 2.0 上使用给定模型获取梯度时遇到问题
- powershell - powershell 检查布尔环境变量
- javascript - dayjs 在日和小时中的两个日期之间的差异
- java - 如何从 onBindViewHolder 中获取 spinner 的值
- java - 应用程序的 onPause、onBackPressed 和 onResume 上的 MediaPlayer 行为
- bigcartel - 从下拉移动导航菜单中删除页面 Big Cartel
- c# - 如何同步 WPF 中的多个切换按钮?