Rubyで配列の一部を返す方法は?


125

Pythonのリストでは、次のコードを使用してリストの一部を返すことができます。

foo = [1,2,3,4,5,6]
bar = [10,20,30,40,50,60]
half = len(foo) / 2
foobar = foo[:half] + bar[half:]

Rubyは配列ですべてを行うので、それに似たものがあるかどうか疑問に思います。

回答:


192

はい、RubyにはPythonと非常によく似た配列スライス構文があります。ここでri、配列のインデックスメソッドのドキュメントは:

--------------------------------------------------------------- Array#[]
     array[index]                -> obj      or nil
     array[start, length]        -> an_array or nil
     array[range]                -> an_array or nil
     array.slice(index)          -> obj      or nil
     array.slice(start, length)  -> an_array or nil
     array.slice(range)          -> an_array or nil
------------------------------------------------------------------------
     Element Reference---Returns the element at index, or returns a 
     subarray starting at start and continuing for length elements, or 
     returns a subarray specified by range. Negative indices count 
     backward from the end of the array (-1 is the last element). 
     Returns nil if the index (or starting index) are out of range.

        a = [ "a", "b", "c", "d", "e" ]
        a[2] +  a[0] + a[1]    #=> "cab"
        a[6]                   #=> nil
        a[1, 2]                #=> [ "b", "c" ]
        a[1..3]                #=> [ "b", "c", "d" ]
        a[4..7]                #=> [ "e" ]
        a[6..10]               #=> nil
        a[-3, 3]               #=> [ "c", "d", "e" ]
        # special cases
        a[5]                   #=> nil
        a[6, 1]                #=> nil
        a[5, 1]                #=> []
        a[5..10]               #=> []

5
なぜa [5、1]はa [6、1]と違うのですか?
dertoni 2011年


25
a[2..-1]3番目の要素から最後の要素に移動します。a[2...-1]3番目の要素から最後から2番目の要素まで取得します。
賢いプログラマ

1
@Rafehは、このジャンクがどのように機能するのか疑問に思って乾杯し、-1でトリックを行いました
Ben Sinclair

@CleverProgrammerの構文は、受け入れられている回答よりもPythonにかなり近いです。Rubyは大好きですが、Pythonの構文は短くて明確です。ボーナスとして、それはステップを指定することが可能である:range(10)[:5:-1]
エリックDuminil


17

これには、slice()を使用できます。

>> foo = [1,2,3,4,5,6]
=> [1, 2, 3, 4, 5, 6]
>> bar = [10,20,30,40,50,60]
=> [10, 20, 30, 40, 50, 60]
>> half = foo.length / 2
=> 3
>> foobar = foo.slice(0, half) + bar.slice(half, foo.length)
=> [1, 2, 3, 40, 50, 60]

ちなみに、私の知る限りでは、Pythonの「リスト」は動的に成長する配列を効率的に実装しただけです。最初の挿入はO(n)、最後の挿入は償却済みO(1)、ランダムアクセスはO(1)です。


2番目のスライスでバー配列を使用するつもりですか?
サムエル

参考:slice!()配列は変更されず、「インデックス(オプションで長さまでの要素)または範囲によって指定された要素が削除されます」。あたりruby-doc.org/core-2.2.3/Array.html#method-i-slice-21
ジョシュア・ピンター

7

別の方法は、範囲メソッドを使用することです

foo = [1,2,3,4,5,6]
bar = [10,20,30,40,50,60]
a = foo[0...3]
b = bar[3...6]

print a + b 
=> [1, 2, 3, 40, 50 , 60]

3

Ruby 2.6の開始範囲/終了範囲

(..1)
# or
(...1)

(1..)
# or
(1...)

[1,2,3,4,5,6][..3]
=> [1, 2, 3, 4]

[1,2,3,4,5,6][...3]
 => [1, 2, 3]

ROLES = %w[superadmin manager admin contact user]
ROLES[ROLES.index('admin')..]
=> ["admin", "contact", "user"]

2

私はこれの範囲が好きです:

def first_half(list)
  list[0...(list.length / 2)]
end

def last_half(list)
  list[(list.length / 2)..list.length]
end

ただし、エンドポイントが範囲に含まれているかどうかについては、十分に注意してください。これは、真ん中を突破する場所を選択する必要がある奇数長のリストでは重要になります。そうしないと、真ん中の要素が二重に数えられることになります。

上記の例では、一貫して中間要素を後半に配置します。


(list.length / 2.0).ceil必要に応じて、前半に一貫して中間要素を配置するために使用できます。
Sorashi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.