4

最近、「Ruby のスタイルの要素 #3: 何かが配列であることを確認する」に出くわしました。

TL;DR: Array()Ruby のメソッドは、入力したものをすべて配列に変換し、正しい結果がどうあるべきかを推測しようとします。

Array(1)     # => [1]
Array([1,2]) # => [1,2]
Array(nil)   # => []

では、何をArray({a: :b})返しますか?ハッシュを値として持つ配列を返すと思います: [{a: :b}].

ただし、ハッシュは直接配列に変換されます: [:a, :b].

ハッシュを配列 ( ) に入れたいだけではありません[{a: :b}]。何を入れても配列を返す機能が欲しいです。Array()すでにそれを行っていますが、予想外の方法でハッシュを配列に変換します。

したがって、基本的に機能は次のようになります。

NewFancyArrayMethod({a: :b}) # => [{a: :b}]
NewFancyArrayMethod([{a: :b}, {c: :d}]) # => [{a: :b}, {c: :d}]

2 番目の部分は、 によってすでに満たされていArray()ます。

values = [values] unless values.is_a? Array記事が指摘しているように、私はのようなことができることを知っています。Array()ただし、既に行っているように、この変換を私から抽象化するメソッドが必要です。唯一の問題はArray()、ハッシュを他の「単一」値 (文字列、整数、オブジェクトなど) とは異なる方法で扱うことです。私は単に、ケースごとに異なる処理をしたくありません。

4

4 に答える 4

8

では、何をArray({a: :b})返しますか?ハッシュを値として持つ配列を返すと思います: [{a: :b}].

あなたの仮定は間違っています。Kernel#Array試行することによって引数を変換しますarg(その順序で):

  1. arg.to_ary
  2. arg.to_a
  3. そして最後に作成します[arg]

例:

Array(1)        #=> [1]

これは(3)が原因です。ないFixnum#to_aryFixnum#to_a

Array([1, 2])   #=> [1, 2]

[[1, 2]]これは(1) のため返されません。Array#to_ary戻り値self

Array(nil)      #=> []

[nil]これは(2) のため返されません。ありませんNilClass#to_aryが、NilClass#to_a常に空の配列を返す」があります。

Array({a: :b})  #=> [[:a, :b]]

このように (2) の理由でArray(nil)返されません。[{a: :b}]ありませんHash#to_aryが、Hash#to_ahshを[キー、値]配列のネストされた配列に変換します。」

Array(Time.now) #=> [33, 42, 17, 22, 8, 2013, 4, 234, true, "CEST"]

これはTime#to_a返されます... 「時間の値の10要素配列」

結論:

Kernel#Array期待どおりに動作しHash#to_aますが、犯人です。(またはto_a一般的に)

何を入れても配列を返す機能が欲しいです。

HashArrayは異なるオブジェクトです。タイプを確認できます(Kernel#Arrayこれも行います):

def hash_to_array(h)
  h.is_a?(Array) ? h : [h]
end

または拡張Hash(またはObject)およびArray

class Hash # or Object
  def my_to_a
    [self]
  end
end

class Array
  def my_to_a
    self
  end
end

代替実装についてはコメントを参照してください。

于 2013-08-22T14:25:47.780 に答える
1

次に、以下のようにモンキー パッチを実行します。

class Hash
  def fancyarraymethod
    [self]
  end
end
class Array
  def fancyarraymethod
    self
  end
end

{a: :b}.fancyarraymethod # => [{a: :b}]
[{a: :b}, {c: :d}].fancyarraymethod # => [{a: :b}, {c: :d}]
于 2013-08-22T13:26:57.590 に答える
1

作業しているのが配列なのかハッシュなのかわからないflatten場合は、後者の場合にネストされた配列で終わるのを防ぐために使用できます。このような:

[foo].flatten

# E.g.
foo = [{:a => :b}, {:c => :d}]
[foo] #=> [[{:a => :b}, {:c => :d}]] -- Nested, call flatten to fix that
[foo].flatten #=> [{:a => :b}, {:c => :d}]

foo = {:a => :b}
[foo] #=> [{:a => :b}] -- Not nested, call flatten anyway just in case
[foo].flatten #=> [{:a => :b}]

これは、文字列、整数、およびオブジェクトに対しても機能します。

foo = 'bar'
[foo].flatten #=> ['bar']

foo = 1
[foo].flatten #=> [1]

foo = Object.new
[foo].flatten #=> [#<Object:0x00000100a8daf8>]

いずれにせよ、あなたはあなたが望むものを手に入れます。

于 2013-08-22T13:37:20.907 に答える