首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Ruby -优雅地将变量转换为数组(如果尚未转换为数组

Ruby -优雅地将变量转换为数组(如果尚未转换为数组
EN

Stack Overflow用户
提问于 2013-08-21 21:26:49
回答 9查看 90.6K关注 0票数 131

给定一个数组、单个元素或nil,就可以得到一个数组-后两个数组分别是一个单元素数组和一个空数组。

我错误地认为Ruby会这样工作:

代码语言:javascript
复制
[1,2,3].to_a  #= [1,2,3]     # Already an array, so no change
1.to_a        #= [1]         # Creates an array and adds element
nil.to_a      #= []          # Creates empty array

但你真正得到的是:

代码语言:javascript
复制
[1,2,3].to_a  #= [1,2,3]         # Hooray
1.to_a        #= NoMethodError   # Do not want
nil.to_a      #= []              # Hooray

因此,为了解决这个问题,我需要使用另一种方法,或者我可以通过修改我打算使用的所有类的to_a方法来元程序-这对我来说不是一个选择。

所以它是一个方法:

代码语言:javascript
复制
result = nums.class == "Array".constantize ? nums : (nums.class == "NilClass".constantize ? [] : ([]<<nums))

问题是它有点乱。有没有一种优雅的方式来做到这一点呢?(如果这是解决这个问题的Ruby方式,我会很惊讶)

这有哪些应用程序?为什么要转换为数组呢?

在Rails的ActiveRecord中,调用user.posts将返回一个帖子数组、单个帖子或nil。在编写处理结果的方法时,最容易的假设是该方法将接受一个数组,该数组可以有零个、一个或多个元素。示例方法:

代码语言:javascript
复制
current_user.posts.inject(true) {|result, element| result and (element.some_boolean_condition)}
EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2013-08-21 21:35:28

[*foo]Array(foo)在大多数情况下都可以工作,但在某些情况下,比如哈希,它会把它搞乱。

代码语言:javascript
复制
Array([1, 2, 3])    # => [1, 2, 3]
Array(1)            # => [1]
Array(nil)          # => []
Array({a: 1, b: 2}) # => [[:a, 1], [:b, 2]]

[*[1, 2, 3]]    # => [1, 2, 3]
[*1]            # => [1]
[*nil]          # => []
[*{a: 1, b: 2}] # => [[:a, 1], [:b, 2]]

我能想到的唯一可行的方法就是定义一个方法。

代码语言:javascript
复制
class Object; def ensure_array; [self] end end
class Array; def ensure_array; to_a end end
class NilClass; def ensure_array; to_a end end

[1, 2, 3].ensure_array    # => [1, 2, 3]
1.ensure_array            # => [1]
nil.ensure_array          # => []
{a: 1, b: 2}.ensure_array # => [{a: 1, b: 2}]
票数 168
EN

Stack Overflow用户

发布于 2014-03-16 12:59:06

使用ActiveSupport (Rails):Array.wrap

代码语言:javascript
复制
Array.wrap([1, 2, 3])     # => [1, 2, 3]
Array.wrap(1)             # => [1]
Array.wrap(nil)           # => []
Array.wrap({a: 1, b: 2})  # => [{:a=>1, :b=>2}]

如果您没有使用Rails,您可以定义自己的方法,类似于the rails source

代码语言:javascript
复制
class Array
  def self.wrap(object)
    if object.nil?
      []
    elsif object.respond_to?(:to_ary)
      object.to_ary || [object]
    else
      [object]
    end
  end
end
票数 131
EN

Stack Overflow用户

发布于 2015-04-03 19:38:15

最简单的解决方案是使用[foo].flatten(1)。与其他建议的解决方案不同,它将很好地适用于(嵌套)数组、散列和nil

代码语言:javascript
复制
def wrap(foo)
  [foo].flatten(1)
end

wrap([1,2,3])         #= [1,2,3]
wrap([[1,2],[3,4]])   #= [[1,2],[3,4]]
wrap(1)               #= [1]
wrap(nil)             #= [nil]
wrap({key: 'value'})  #= [{key: 'value'}]
票数 21
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18358717

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档