在这种情况下如何使用Ruby数组?

时间:2018-07-04 21:26:39

标签: arrays ruby

这是一个红宝石数组:

array = ['x', 3, 0, 4, 4, 7]

我想通过array进行映射,将数组中的每个整数(0除外)减去2,然后返回一个新数组。

当有字母时,将不会对字母进行任何更改。

示例输出:

['x', 1, 0, 2, 2, 5]

这就是我所拥有的,但是我收到了错误消息:“未定义的方法整数?”有人可以告诉我这是什么问题吗?

    def minusNumber(array)
     array.map do |e|
      if e.integer? && e !== 0
      e - 2
      end
     end
    end

6 个答案:

答案 0 :(得分:2)

这是另一种看法:

{
    "index": "notifications_production",

    "sort" : {"created_at" : {"order" : "desc"}},

    "query": { 
        "bool": { 
          "must": [
            { "match_all": {} }
          ],
          "filter": [ 
            { "match":  { "company_id": 5054 }},
                {
                    "range" : {
                        "created_at" : {
                            "gte" : "now-30d",
                            "lte" : "now"
                        }
                    }
                }
            ]
        }
      },


     "script_fields" : {
        "sequence2" : {
            "script" : {
                "lang": "painless",
                "source": "'<a href=#>' + params._source.file_name + '</a>'"
            }
        }
    },

    "_source": true   
}

很遗憾,您必须保留没有减去2的元素。我真的很想做这样的事情

array = ['x', 3, 0, 4, 4, 7]

transformed = array.map do |e|
  case e
  when 0, String
    e
  when Integer
    e - 2
  else
    fail 'unexpected input'
  end
end

transformed # => ["x", 1, 0, 2, 2, 5]

还找不到方法(保留未处理的项目)。

答案 1 :(得分:2)

此处的其他答案将与您当前的输入配合使用。像这样:

def minusNumber(array)
  array.map do |e|
    if e.is_a?(Integer) && e != 0
      e - 2
    else
      e
    end
  end
end

但是这里有一个更灵活的解决方案。对于您现在所在的位置,这可能有点太先进了,但是所有学习都是不错的学习:-)

Ruby是一种允许变量中具有多态性的语言。使用方法的示例输入,您可以看到变量e可以包含String对象或Integer对象。但是它实际上可能包含 any 类型的对象,并且Ruby不会在乎一点,除非它在使用变量时遇到错误。

所以。在您的示例中,您需要在输出中保留Integer。但是,如果将来需要传递包含一些Score对象的数组,而在输出中也需要这些对象,该怎么办?这是您甚至还没有写过的全新课程,但是您知道以后会继续学习。有一种方法可以重新编写将要在将来使用的类的方法,以及将来可能编写的所有其他Integer类型的类。

代替使用#is_a?检查对象的类型,而使用#respond_to?检查对象实现的方法。

任何可用作整数should implement the #to_int method的类。 Integer当然可以,您将来的Score类可以,但是String可以。其他不能视为整数的类也没有。因此,这将适用于所有类型的值,正确地将响应#to_int的值与不响应的值分开。

def minusNumber(array)
  array.map do |e|
    if e.respond_to?(:to_int) && e != 0
      e - 2
    else
      e
    end
  end
end

同样,这些东西可能会有点高级,但是早点养成习惯就变量的方法(而不是类型)进行思考是一种很好的习惯。这种思维方式将在以后帮助您。

答案 2 :(得分:0)

又矮又甜。

array.map { |v| v.is_a?(Integer) && !v.zero? ? v - 2 : v }

这消除了所有不必要的case语句,多次迭代和转换。只需取每个元素,如果它是一个整数且大于0,则减去2,否则不执行任何操作。

答案 3 :(得分:0)

您可以执行此操作而无需检查类型。

  

使用kind_of?是一种代码气味,说明您的代码是过程性的,而不是面向对象的…   https://www.sandimetz.com/blog/2009/06/12/ruby-case-statements-and-kind-of

def someMethod(arr)
  arr.map do |item|
    next item unless item.to_i.nonzero?
    item - 2
  end
end

someMethod(["x", 3, 0, 4, 4, 7])

> ["x", 1, 0, 2, 2, 5]

答案 4 :(得分:-1)

如上面的注释中所述,您应该使用is_a?方法检查元素的数据类型。下面的代码应按预期工作:

 def minusNumber(array)
   array.map do |e|
     if e.is_a?(String) || e == 0
       e
     else
       e - 2
     end
   end
 end

代替 if 语句,您也可以这样做:

(e.is_a?(String) || e == 0 ) ? e : e-2

请注意,除非使用map!

,否则原始对象不变。

答案 5 :(得分:-1)

我认为这是清晰而优雅的:

array.map { |v| v.is_a?(Integer) && v == 0 ? v : v -2 }