【问题标题】:Ruby - test for arrayRuby - 测试数组
【发布时间】:2010-12-04 09:57:17
【问题描述】:

正确的方法是:

is_array("something") # => false         (or 1)

is_array(["something", "else"]) # => true  (or > 1)

或获取其中的项目数?

【问题讨论】:

  • 你想要一个实际的数组,还是只是类似数组的东西?
  • Ruby 没有类型安全。不要担心你的变量是否是一个数组。该方法应该假设它是,然后继续调用它的计数:my_array.count
  • 请阅读 zgchurch 和 DigitalRoss 的答案以获得更惯用的 Ruby。

标签: ruby syntax


【解决方案1】:

您可能想使用kind_of()

>> s = "something"
=> "something"
>> s.kind_of?(Array)
=> false
>> s = ["something", "else"]
=> ["something", "else"]
>> s.kind_of?(Array)
=> true

【讨论】:

  • 还有is_a?instance_of?。见stackoverflow.com/questions/3893278/…
  • 类型检查适用于 Java。继续,只需在变量上调用 count 。编写单元测试以确保该方法按预期工作。
  • @user132447 实际上 java 是类型安全的,所以你不必担心检查任何类型
  • 我现在对此投了反对票,因为我认为这不是像 Ruby 这样的语言的好习惯。 @zgchurch 的答案显然是对这个问题的一种更惯用的方法。在这种情况下,我认为尝试弄清楚 OP 的含义比盲目地给他一把霰弹枪更有意义......
  • 为什么要使用kind_of?() 而不是其他解决方案?对您的答案优于其他答案的一些解释将对未来的读者有所帮助。
【解决方案2】:

你确定它需要是一个数组吗?您也许可以使用respond_to?(method),这样您的代码就可以用于不一定是数组的类似事物(可能是其他一些可编号的事物)。如果您确实需要array,那么描述Array#kind\_of? 方法的帖子最好。

['hello'].respond_to?('each')

【讨论】:

  • 在这种情况下,我确信它将是一个数组。但也很高兴知道这种方法。 +1
  • 有趣的想法,我在数据结构上使用 push/pop。除了数组之外的任何东西都会响应这些方法吗?
  • 如果你想要更多类似数组的东西,你可能想要respond_to?(:to_ary)
  • 一般来说,这是面向对象开发的一个很好的实践。我读到有人基本上说过:不要想象你正在调用你的对象的方法。您正在向他们发送消息。如果一个对象知道如何响应您的消息,那么您不必关心它是什么类,或者它是否有一个名为那个的方法,或者它是否通过 method_missing 动态创建响应。重要的是,它能回复你的信息吗?这允许更好地抽象功能和实现。您可以更改以后使用的对象,只要它仍然正确响应。
  • 唯一的问题是说我想检查某个东西是否是索引可迭代的,所以数组、链表等会很酷,但我不想要像哈希这样的键值存储?
【解决方案3】:

无需测试Array,,只需将您得到的任何内容转换为一级Array,,这样您的代码只需要处理一种情况。

t = [*something]     # or...
t = Array(something) # or...
def f *x
    ...
end

Ruby 有多种方法来协调可以接受一个对象或一个对象数组的 API,所以,猜测一下为什么你想知道某事物是否是一个数组,我有一个建议.

splat 运算符包含许多神奇的 you can look up, 或者您可以调用 Array(something),如果需要,它将添加一个数组包装器。在这种情况下,它类似于[*something]

def f x
  p Array(x).inspect
  p [*x].inspect
end
f 1         # => "[1]"
f [1]       # => "[1]"
f [1,2]     # => "[1, 2]"

或者,您可以在参数声明中使用 splat,然后使用 .flatten,为您提供不同类型的收集器。 (就此而言,您也可以拨打上面的.flatten。)

def f *x
  p x.flatten.inspect
end         # => nil
f 1         # => "[1]"
f 1,2       # => "[1, 2]"
f [1]       # => "[1]"
f [1,2]     # => "[1, 2]"
f [1,2],3,4 # => "[1, 2, 3, 4]"

而且,感谢gregschlom,有时只使用Array(x) 会更快,因为当它已经是Array 时,它不需要创建新对象。

【讨论】:

  • 所以你是说如果它是一个单一的项目,它会使其成为一个包含单一项目的数组?
  • 是的,如果它已经是一个数组,它会保留它而不添加第二个数组包装器。
  • 别忘了:[*nil] => []。所以你最终可能会得到一个空数组。
  • 使用Array(foo)[*foo]高效得多
【解决方案4】:

[1,2,3].is_a? Array 计算结果为真。

【讨论】:

  • 这对网站上已存在近七年的答案有什么补充......?
  • @Carpetsmoker 在整个线程中没有引用is_a? 的简洁答案。最接近的是[1,2,3].is_a? Enumerable。我仍然认为得到这个答案是值得的。
  • 你知道..你是对的......我可以发誓我之前在上面看到过 :-/ 点个赞!
【解决方案5】:

听起来您正在寻找具有某种物品概念的东西。因此,我建议查看它是否为Enumerable。这也保证了#count的存在。

例如,

[1,2,3].is_a? Enumerable
[1,2,3].count

请注意,虽然 sizelengthcount 都适用于数组,但 count 在这里是正确的含义 - (例如,'abc'.length'abc'.size 都适用,但 'abc'.count不能那样工作)。

注意:字符串 is_a?可枚举,所以也许这不是你想要的……取决于你对对象数组的概念。

【讨论】:

    【解决方案6】:

    试试:

    def is_array(a)
        a.class == Array
    end
    

    编辑:另一个答案比我的要好得多。

    【讨论】:

      【解决方案7】:

      还可以考虑使用Array()。来自Ruby Community Style Guide

      在处理时使用 Array() 而不是显式的 Array 检查或 [*var] 有一个变量,你想把它当作一个数组,但你不确定 这是一个数组。

      # bad
      paths = [paths] unless paths.is_a? Array
      paths.each { |path| do_something(path) }
      
      # bad (always creates a new Array instance)
      [*paths].each { |path| do_something(path) }
      
      # good (and a bit more readable)
      Array(paths).each { |path| do_something(path) }
      

      【讨论】:

      • 这会在传递哈希时产生意想不到的结果,因为to_a会在每个添加到新数组的参数上调用,所以Array({id: 100})返回[[:id, 100]]
      猜你喜欢
      • 2020-09-25
      • 1970-01-01
      • 1970-01-01
      • 2011-10-02
      • 2010-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多