【问题标题】:Check array's elements are of the same size检查数组的元素大小相同
【发布时间】:2026-01-22 18:50:01
【问题描述】:

有没有一种最有效的方法来检查数组元素的大小是否相同?

[[1,2], [3,4], [5]] => false

[[1,2], [3,4], [5,6]] => true

我有什么:

def element_of_same_size?(arr)
  arr.map(&:size).uniq.size == 1
end

另一种解决方案:

def element_of_same_size?(arr)
  arr[1..-1].each do |e|
    if e.size != arr.first.size
      return false
    else
      next
    end
  end
  return true
end

当它发现一个元素的大小与第一个不同时,这个会立即返回 false。

有没有最好的方法来做到这一点? (当然……)

【问题讨论】:

    标签: ruby arrays


    【解决方案1】:

    使用Enumerable#all? 方法怎么样?

    def element_of_same_size?(arr)
      arr.all? { |a| a.size == arr.first.size }
    end
    
    element_of_same_size?([[1,2], [3,4], [5]])
    # => false
    
    element_of_same_size?([[1,2], [3,4], [5, 6]])
    # => true
    

    【讨论】:

    • 这个问题的完美答案。
    【解决方案2】:

    再交付一个单行:

    您可以使用chunkone?

    [[1,2], [3,4], [7,8], [5,6]].chunk(&:size).one?
    

    【讨论】:

    • [[1,2], [3,4], [7,8], [5,6,9]].partition(&:size).last.empty? 也是true
    • @juanitofatas 正确,删除它,谢谢!无论如何,大块和一个更漂亮
    • chunk 方法真的很慢,1 秒以上评估这 100,000 次(见我的回答)
    • @Aaron_H 好吧,我现在看到了,100'000 次。实际上是 Enumerator#one? 有点贵,是的。但是,嘿,它是一个单线器,2x-4x 并不是一个极端的性能开销。
    【解决方案3】:

    我喜欢 toro2k 的回答。我只是想添加将方法添加到数组类本身的可能性,并警告您不是数组但响应 size 方法的元素仍可能返回 true。 (编辑:如果为空数组则为 false)

    class Array
      def same_element_size?
        return false if self.empty?
        sz = self.first.size
        self.all? {|k| k.size==sz}
      end
    end
    
    ar  = [[1,2], [3,4], [5]]
    ar2 = [[1,2], [3,4], [5,6]]
    ar3 = [[1,2], 'hi', [4,5]]
    
    [[], ar, ar2, ar3].each {|array|
      puts "%30s --> %s" % [array.inspect, array.same_element_size?]
    }
    
    #                            [] --> false
    #         [[1, 2], [3, 4], [5]] --> false
    #      [[1, 2], [3, 4], [5, 6]] --> true
    #        [[1, 2], "hi", [4, 5]] --> true
    

    【讨论】:

      【解决方案4】:

      只是为了好玩,如果您选择扩展Array,您可以选择更灵活的方法,例如实现same? 方法:

      class Array
        def same? &block
          if block_given?
            f = block.call(first)
            all? {|a| block.call(a) == f}
          else
            all? {|a| a == first }
          end
        end
      end
      

      这允许:

      [[1,2], [5,6], [8,9]].same?(&:size)
      

      [[1,2], [7,8], [5,6], [8,9]].same?(&:max)
      

      或者只是(默认会与==比较)

      [[1,2], [7,8], [5,6], [8,9]].same?
      

      【讨论】:

        【解决方案5】:

        一些基准测试:

                                          user     system      total        real
          standalone all                0.234000   0.000000   0.234000 (  0.246025)
          class method all              0.234000   0.000000   0.234000 (  0.235024)
          class method transpose        0.920000   0.000000   0.920000 (  0.940094)
          chunk and one?                1.591000   0.000000   1.591000 (  1.610161)
        

        我的钱花在了使用 Enumerable#all 的类方法上?通过 toko2k

        【讨论】:

          【解决方案6】:

          如果处理非嵌套数组的数组,您可以测试以确保矩阵是正方形的。它将递归数组抛出窗口,但有点简洁。

          require 'matrix'
          
          a1 = [[1,2],[3,4],[5,6]]
          a2 = [[1,2,3],[4,5,6]]
          a3 = [[1,2],3,4,[5,6]]
          
          Matrix[a1].square? == true
          Matrix[a2].square? == true
          Matrix[a3].square? == false
          

          【讨论】: