如何测试列中的所有项是否相同

时间:2014-12-02 20:18:23

标签: ruby multidimensional-array

我正在编写一个程序,需要检查二维数组的每列中的值是否相等。列数在5处也是静态的。

目前我有一个if语句,它从列到列进行迭代,并在一个巨大的支票中比较该列中的所有值:

if column[0][i] == column[1][i] && column[0][i] == column[2][i]

编辑:对不起,我并不打算混淆。该阵列创建了一个5x5游戏板。行指的是每个单独的数组,列指的是每个数组中的第n个数字。

1 个答案:

答案 0 :(得分:2)

你的问题有些令人困惑,我认为因为在大多数代码中我都遇到过表示使用数组的行和列的结构,“outer”数组表示行,“inner”数组表示列。例如:

arr = [ [ a, b ],
        [ x, y ] ]

在通常的模型中,(ab)是“row”0,(xy)是第1行。这使得{{{ 1}},a)第0列和(xb)第1列。

但您的代码表明您的结构已反转,第0行为(ya),第1行为(xb),这使得(ya)第0列和(bx)第1列,所以我会这样回答。如果我们希望列中的每个值都等于同一列中的每个值(即y),那么这很容易。假设我们有以下数据:

a == b && x == y

要检查“column”0中的每个值是否等于第0列中的每个其他值,我们可以这样做:

arr = [ [ 10, 10, 10, 10 ],  # <-- Column 0
        [ 11, 11, 11, 11 ],  # <-- Column 1
        [ 12,  0, 12, 12 ] ] # <-- Column 2

这只是将列中的每个项目与第一个项目arr[0].all? {|item| item == arr[0][0] } # => true 进行比较,并在找到不相等的项目后立即返回arr[0][0](如果不相等则返回false )。

为了对每个“行”执行此操作,我们可以将第一个all?包装在另一个中:

true

编辑:如果您的数组看起来像这样:

arr.all? do |sub_arr|
  sub_arr.all? {|item| item == sub_arr.first }
end
# => false

解决问题的一种方法是:

arr = [ [ 10, 11, 12 ],
        [ 10, 11,  0 ],
        [ 10, 11, 12 ],
        [ 10, 11, 12 ] ]
#          │   │   └─ Column 2
#          │   └─ Column 1
#          └─ Column 0

第一行将第一行分配给first_row, *rest = arr rest.all? do |row| row.each_with_index.all? do |item, col_idx| row[col_idx] == first_row[col_idx] end end ,其余行分配给first_row。然后,对于rest中的每一行,我们使用rest将每个项目与all?中的相应项目进行比较。

P.S。另一种解决方法是:

first_row

Array#transpose只需交换行和列(即将arr.transpose.all? {|row| row.uniq.size == 1 } 转换为[[a,b],[x,y]]),然后在[[a,x],[b,y]]中我们使用计算每个“列”中的唯一值(现在是一排)。如果有多个唯一值,我们知道它们并不完全相同。当然,这有更多的开销:all?transpose迭代每个值并返回一个新数组,而上面的方法一找到任何不匹配的值就会停止。但是只给出25个项目可能不会那么糟糕,这取决于你需要它运行的频率。

P.P.S。我很好奇第一种方法的表现比第二种方法好多少。你可以在这里看到代码和结果:https://gist.github.com/jrunning/7168af45c5fa5fb4ddd3因为第一种方法是“短路”-i.e。一旦发现“错误”值,它就会停止 - 随着“错误”值增加的概率,它会变得更快。如果任何行有错误值的可能性为33%,则第一种方法比第二种方法快33%。有75%的几率,第一个比第二个快80%。我意识到这比你需要的更多信息,但我发现它很有趣。