【问题标题】:Ruby - Problem to test Object.class into ArrayRuby - 将 Object.class 测试为数组的问题
【发布时间】:2020-09-25 04:57:12
【问题描述】:

今天,在我的代码中,如果文件存在,如果数组不包含特定类,我会尝试做一些事情,但测试不起作用。

def LoadPackagesDatabase
        packagesFiles = Dir['Packages/*.rb']
        packagesClass = []
        packagesFiles.each do |file|
            load file
            filename = file.sub('.rb', '')
            packagesClass.append(Object.const_get(filename.sub('Packages/','')).new)
        end

        if File.exist?("PackagesDatabase.rb")
            $PackagesDatabase = Marshal.load(File.read("PackagesDatabase.rb"))

            packagesClass.each do |package|
               if !$PackagesDatabase.include?(package.class)
                   $PackagesDatabase.append(package)
               end
            end
            File.delete("PackagesDatabase.rb")
            packagesDatabaseFile = File.open("PackagesDatabase.rb",'w')
            packagesDatabaseFile.write(Marshal.dump($PackagesDatabase))
            packagesDatabaseFile.close
        else
            $PackagesDatabase = packagesClass
            packagesDatabaseFile = File.open("PackagesDatabase.rb",'w')
            packagesDatabaseFile.write(Marshal.dump(packagesClass))
            packagesDatabaseFile.close
        end

    end

我不想测试数组是否包含相同的对象,但如果数组包含特定的类。

【问题讨论】:

  • 澄清一下,如果你有array = ['foo', 23, 42],那么array.contains_class?(Numeric) 是真的但array.contains_class?(Time) 是假的?

标签: arrays ruby class


【解决方案1】:

Array#include? 进行简单的相等性检查。对于更通用的检查,请使用 any?all?none?。他们都拿积木来做比较。

if $PackagesDatabase.none? { |item| item.is_a?(package.class) }
  $PackagesDatabase.append(package)
end

请注意,我没有使用item.class == package.class,这需要完全匹配。相反,我使用的是is_a?。这确保子类也将匹配。例如,23.class == Numeric 为假,而23.is_a?(Numeric) 为真。使用哪个取决于您的具体情况,但通常您应该使用is_a? 以使您的代码更加灵活。

【讨论】:

    【解决方案2】:

    可以使用强大的Enumerable#grep,它使用=== 方法进行选择。假设,例如,

    arr = [1, 'cat', 2.3]
    

    可以这样写,例如:

    arr.grep(Float).any?   #=> true
    arr.grep(Numeric).any? #=> true
    arr.grep(Complex).any? #=> false
    arr.grep(Array).any?   #=> false
    

    在评估arr.grep(Float) 时,方法Module#===1 用于进行以下计算:

    Float === 1     #=> false 
    Float === 'cat' #=> false
    Float === 2.3   #=> true 
    

    可以改为写

    arr.any? { |o| Float === o } #=> true
    

    它的优点是它短路计算,这意味着如果并且当块返回true 时,arr 的元素的枚举将停止。相比之下,arr.grep(Float).any? 枚举整个数组。

    1.注意Float.method(:===).owner #=> Module.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-04
      • 2020-01-19
      • 1970-01-01
      • 2011-04-05
      • 2020-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多