Ruby配列の最後の要素を除くすべて


139

Rubyの配列があるとしましょう

a = [1, 2, 3, 4]

最初のアイテム以外すべてが必要な場合は、と書けa.drop(1)ます。これは素晴らしいことです。もし最後のアイテム以外が欲しいなら、このようにしか考えられない

a[0..-2]   # or
a[0...-1]

しかし、これらはどちらもを使用するほどきれいには見えませんdrop。他に欠けている組み込みの方法はありますか?


globalnerdy.com/2008/07/10/…によると、ドロップはルビー1.8.6ではなくルビー1.9です
Andrew Grimm

パフォーマンスについてはどうですか?これらの答えを何千回も繰り返し使用した場合、どれが勝つでしょうか?
Ninad、2011

言い換えると、どのソリューションが内部でアレイを通過しないのですか?
Ninad、2011

別の方法では、a-([a.size])
John

回答:


128

たぶん...

a = t               # => [1, 2, 3, 4]
a.first a.size - 1  # => [1, 2, 3]

または

a.take 3

または

a.first 3

または

a.pop

最後を返し、配列の前にすべてを残します

または、夕食時にコンピュータを機能させる:

a.reverse.drop(1).reverse

または

class Array
  def clip n=1
    take size - n
  end
end
a          # => [1, 2, 3, 4]
a.clip     # => [1, 2, 3]
a = a + a  # => [1, 2, 3, 4, 1, 2, 3, 4]
a.clip 2   # => [1, 2, 3, 4, 1, 2]

5
メソッドを追加することArrayは、私にとって最良のアプローチのようです。ほとんどのプロジェクトは、core_ext.rbこのような小さな拡張子の付いたファイルになってしまいます。一部のライブラリは、たとえば次のような実質的にすべての拡張機能ActiveSupportです。
rfunduk 2009年

それは面白いです、それがどれほど一般的であるのか疑問に思いました。人々は詩モードについてどう思いますか?
DigitalRoss

5
誰かがこのclipメソッドをRubyコミュニティにどのように提出しますか?私は本当にこれがそこにあるはずだと思います、そしてモンキーパッチは間違ったものです。
Droogans 2013

7
私はa.reverse.drop(1).reverse戦略が好きです。;-)
Alex

92

好奇心から、a[0...-1]いかがですか?配列のスライスを取得したいので、スライス演算子は慣用的な選択のように見えます。

しかし、これを至る所で呼び出す必要がある場合は、DigitalRossが提案するように、Arrayクラスにわかりやすい名前のメソッドを追加するオプションが常にあります。おそらくこのように:

class Array
    def drop_last
        self[0...-1]
    end
end

ドロップがとてもきれいなとき、それはちょうどたくさんの混乱のように見えます。それは大したことではありませんが、それが正確に正しいことを一目で確認することは困難です。drop_lastちなみに私はあなたの名前を好む...
ピーター

私は.lengthを使用するよりも-1を使用する方がずっとエレガントです
Will Nathan

好奇心が強い、その3番目の意味は何.ですか?
Joshua Pinter

5
...は最後の項目を含まないことを意味し、-1は最後の項目です。2つのドットを実行した場合、最後のアイテムが含まれます。3つのドットの場合、最後のアイテムは含まれません。
ckim

配列の末尾を取得するためにスライス演算子を使用する場合は注意してください。次の値が返される場合がありnilます:[][1..-1]-> nil[][0...-1]->[]
Michael

57

別のクールなトリック

>> *a, b = [1,2,3]
=> [1, 2, 3]
>> a
=> [1, 2]
>> b
=> 3

Rubyがこれを持っていることに気づかなかった。これa, *b = [1,2,3]で、アレイをクラシックカー/ cdrの方法で確認できます。
Nobbynob Littlun 2014年

正直なところ、私はそのコメントを書いたことすら覚えていません:Dは今それを削除しました...
Petr Bela

Sooooシンプルでいい。THX
microspino 2018

43

pop()配列に対して操作を実行したい場合(最後の項目が削除されることになります)、ポップされた要素の代わりに配列を取得したい場合は、以下を使用できますtap(&:pop)

> arr = [1, 2, 3, 4, 5]
> arr.pop
=> 5
> arr
=> [1, 2, 3, 4]
> arr.tap(&:pop)
=> [1, 2, 3]

この答えは、このユーザーにとって意味的に最も意味のあるものです。ミラー操作は手元にあり、&&簡潔に解釈できる言葉を使用しています。
ジェローム

2
それは巧妙なRubyです。
emptywalls

38

私はそれをこのようにします:

my_array[0..-2]

2
これは素晴らしく機能します。なぜもっと多くの複雑な答えがあるのか​​と混乱しています。これはRubyの新しい追加ですか?
Joshua Pinter、2015

@JoshuaPinter 最初から存在してます。それが断然最善のアプローチであることに同意します。
ジュリアン

23

たとえば、次のように、dropメソッド自体を拡張してみませんか?

class Array
  def drop(n)
    n < 0 ? self[0...n] : super
  end
end

次に、次のように、負のサイズを使用して末尾から要素を削除できます。

[1, 2, 3, 4].drop(-1) #=> [1, 2, 3]
[1, 2, 3, 4].drop(-2) #=> [1, 2]

19

a[0...-1]最良の方法のようです。配列スライス構文は、まさにこの目的のために作成されました...

または、配列を適切に変更してもかまわない場合は、次のように呼び出しますa.pop

>> a = [1, 2, 3, 4]
>> a.pop
>> a
=> [1, 2, 3]

あなたはまた、後で使用するための変数に最後の要素を割り当てることができますb = a.pop
ヴィクトルFonic

12

1行の最後の要素を取り除き、残りを返すには

[1, 2, 4, 5, 6].reverse.drop(1).reverse

でも真剣に

[1,2,3,4][0..-2]
#=> [1,2,3]

11

これが方法です:

[1,2,3,4,5][0..-1-1]

しかし、これがどのように機能するかを説明しましょう:

a = [1,2,3,4,5]

次の例では、0位置から最後までのすべてのレコードを返します

a[0..-1]
=> [1, 2, 3, 4, 5]

次の例は、1つの位置から最後のレコードを返します

a[1..-1]
=> [2, 3, 4, 5]

そしてここにあなたが必要なものがあります。次の例では、0位置から最後の1までのレコードを返します

a[0..-1-1]
=> [1, 2, 3, 4]

1
-2代わりに書くことができます-1-1
bfontaine 2015年

3番目のドットは終了要素を除外するように指示するため、(3番目のドットにa[0...-1]注目して)と同じ結果を得ることができますa[0..-1-1]。詳細はこちらをご覧ください。
ジュリアン


2

回答: a.τwτ、ただし最初にPyperをインストールする必要があります...

イントロPyper: Doが、あなたはLispyのを知っているcarし、cdr「最初の」と配列の「休息」を返しますか?あなたのようなニーズのために、私はこのLispyメカニズムの拡張を行いました。それはと呼ばれpyper、2番目、2番目からの残り、3番目からの残り、3番目からの残り、最後、最後を除くすべてにアクセスすることを可能にします。caarcadrcdadarなどのLispから知られています:

# First, gem install pyper
require 'pyper'
include Pyper
a = %w/lorem ipsum dolor sit amet/
# To avoid confusion with other methods, and also because it resembles a rain gutter,
# Greek letter τ is used to delimit Pyper methods:
aaτ #=> "lorem"
adτ #=> ["ipsum", "dolor", "sit", "amet"]
abτ #=> "ipsum"
aeτ #=> ["dolor", "sit", "amet"]
acτ #=> "dolor" (3rd)
azτ #=> "amet" (last)
ayτ #=> "sit" (2nd from the end)
axτ #=> "dolor" (3rd from the end)

そして最後に、あなたの質問への答え:

awτ #=> ["lorem", "ipsum", "dolor", "sit"] (all except last)

もっとある:

auτ #=> ["lorem", "ipsum", "dolor"] (all except last 2)
a1τ #=> ["lorem", "ipsum"] (first 2)
a8τ #=> (last 2)
a7τ #=> (last 3)

構成:

awydτ #=> "olor" (all except 1st letter of the last word of all-except-last array)

また、コマンド文字には、マップを意味するだけa..fu..zなく0..9、最も重要なものmもあります。

awmbτ #=> ["o", "p", "o", "i"] (second letters of all-except-last array)

しかし、他のコマンド文字は非常に熱く、現時点では簡単に使用できません。


1
私はこれを4月1日に読んでいるので、それは冗談だと思いました...いいえ。Rubyにこのようなものが存在するという考えはありませんでした。:)
Joshua Pinter

1

これにより、元の最後の要素を除くすべての新しい配列が作成されます。

ary2 = ary.dup
ary2.pop

他のいくつかは#popの使用を提案していることに注意してください。配列を適切に変更しても問題ない場合は、それで問題ありません。これで問題ない場合は、この例のように、まず配列を複製してください。


1
配列を適切に変更しても問題ない場合は、#popの使用を提案している人もいます。これで問題ない場合は、この例のように、まず配列を複製してください。
alegscogs

これは重要なコメントです。あなたはそれをあなたの答えに追加することもできます。#popには感嘆符(!)がないため、元の配列を変更するという事実は人々から逃れる可能性があります。
mjnissim 2013年

配列が大きい場合、これは非常に非効率的です。
juliangonzalez 2018

1

私はしばしば、配列の最後のn個の要素以外をすべて欲しがっています。私は他のソリューションよりも読みやすい方法でこれを行うために自分の関数を作り上げました:

class Array
  def all_but_the_last(n)
    self.first(self.size - n)
  end
end

これで、次のことができるようになります。

arr = ["One", "Two", "Three", "Four", "Five"]
# => ["One", "Two", "Three", "Four", "Five"]

arr.all_but_the_last(1)
# => ["One", "Two", "Three", "Four"]

arr.all_but_the_last(3)
# => ["One", "Two"]

arr.all_but_the_last(5)
# => []

arr.all_but_the_last(6)
# ArgumentError: negative array size

ArgumentErrorを故意に許可して、呼び出し元がこのメソッドの使用方法を担当するようにしました。このアプローチについてのコメント/批評を聞きたいです。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.