更有效地比较两个数组中的值的模式

时间:2013-04-24 10:27:20

标签: ruby arrays performance

我需要测试两个数组是否相等,每个数组包含8个整数1..7项。问题在于,这不是我关心的价值本身,而是价值模式。例如:

eq? [ 1,2,3,4, 5,6,7,1 ], [ 1,2,3,4, 7,6,5,1 ] # => true
eq? [ 1,1,2,2, 3,3,4,4 ], [ 3,3,2,2, 1,1,4,4 ] # => true
eq? [ 1,1,1,1, 2,2,2,2 ], [ 1,1,1,2, 1,2,2,2 ] # => false
eq? [ 1,2,1,3, 4,4,5,6 ], [ 7,5,7,6, 2,2,3,4 ] # => true

!编辑的例子,所以第一个参数已经标准化了

注意:数组中间的空格只是为了便于阅读。

我需要这样做数百万次。所以我提出了以下方法。

# this method "standardizes" permutation 2 before comparing to permutation1 which is assumed to already be standardized
def eq? permutation1, permutation2
  next_val = 0
  key = Hash.new { |h,k| h[k] = next_val+=1 }
  permutation1 == permutation2.map { |i| key[i] }
end

permutation1将是少数几个值中的一个,因此可以在测试之前标准化一次,而每个排列2将是唯一的。

但这太慢了!有没有更好的方法来解决这个问题,可能使用相同的方法,但避免使用哈希作为键?还是一种完全不同的方法?

编辑:为了澄清一点,如果你可以替换一个数组中的每个数字或一个数字的子集,两个数组应该被视为相等,这样每个原始数字映射到一个唯一的新数字(即1 => ; 3,3 => 4,4 => 2,2 => 1等),然后两个阵列实际上是相同的。所以它不是价值(它们可以是七种不同的颜色或单词,就像数字一样容易),而不是重要的价值模式。

EDIT2:应用于3位数组的原则意味着:

[1,1,1]匹配所有项目相同的任何数组,

[1,2,3]匹配所有项目不同的任何数组,

[1,1,2]匹配前两个项目相同且第三个不同的任何数组,

[1,2,1]匹​​配任何数组,其中第一个是相同的而第三个但不是第二个,

[1,2,2]匹配任何第二个和第三个相同但第一个不同的数组,

任何三个项目数组都将匹配其中一个。

2 个答案:

答案 0 :(得分:4)

def eq? a, b
  (0...a.length).group_by{|i| a[i]}.values ==
  (0...b.length).group_by{|i| b[i]}.values
end

eq?([1,2,3,4,5,6,7,1], [1,2,3,4,7,6,5,1]) # => true
eq?([1,1,2,2,3,3,4,4], [3,3,2,2,1,1,4,4]) # => true
eq?([1,1,1,1,2,2,2,2], [1,1,1,2,1,2,2,2]) # => false
eq?([1,2,1,3,4,4,5,6], [7,5,7,6,2,2,3,4]) # => true

答案 1 :(得分:1)

您可以通过这种方式重新配制匹配算法:

如果两个元素具有相同数量的元素并且每个元素的表示对象相等,则认为它们是相等的。所表示的对象(或值)是一组唯一对象中的一个,这些对象按其外观的顺序分​​配给原始置换元素。两种排列的唯一对象集是相同的。

示例:从2组8个整数(1..8)开始,比较8种颜色的两种排列。

for each color in both permuations
  find the color in their associated set, use the index in the set as representation
  if not found insert in the next free place and use this place's index as representation
  if representation1 != representation2 return false
continue with next element
return true

主要问题是插入一个置换元素并在以后快速找到它。这就是您必须创建哈希映射的原因。如果你有一个固定(和小)数量的元素,一种可能的优化是使用两个固定长度的固定数组,它可以在每个条目中保存一个permuation元素。将这些数组中的索引用作表示的对象。你需要一个线性搜索来查找数组中的排列,但只有一小组(如上面提到的8),这就像比较一个循环中的8个指针/整数,这应该非常快,当然不会慢于查找hashmap。但是你保存了中间对象的创建。

然而,我自己没有对此进行任何验证。