Ruby dizisinin son öğesi hariç tümü


139

Diyelim ki Ruby dizim var

a = [1, 2, 3, 4]

İlk öğe hariç hepsini istiyorum, yazabilirim a.drop(1), bu harika. Son öğe hariç hepsini istiyorsam , sadece bu şekilde düşünebilirim

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

ancak bunların hiçbiri kullanmak kadar temiz görünmüyor drop. Eksik olduğum başka yerleşik yollar var mı?


Globalnerdy.com/2008/07/10/… 'a göre , yakut 1.8.6 yerine yakut 1.9 olur
Andrew Grimm

Performansa ne dersiniz .. Bu cevapları 1000 kez tekrarlar halinde kullansaydım hangisini kazanırdım?
Ninad

Başka bir deyişle, hangi çözüm kaputun altında diziyi geçmez?
Ninad

başka bir şekilde, a - ([a.size])
John

Yanıtlar:


128

Belki ...

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

veya

a.take 3

veya

a.first 3

veya

a.pop

Sonuncuyu döndürür ve diziyi ondan önce her şeyle birlikte bırakır

veya bilgisayarın akşam yemeği için çalışmasını sağlayın:

a.reverse.drop(1).reverse

veya

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
Bir yöntem eklemek Arraybana en iyi yaklaşım gibi geliyor. Çoğu proje, bunun core_ext.rbgibi küçük uzantılara sahip bir dosya ile sonuçlanır . Bazı kütüphaneler neredeyse tüm uzantılardır: ActiveSupportörneğin.
rfunduk

Bu ilginç, ne kadar yaygın olduğunu merak ettim. İnsanlar şiir modu hakkında ne düşünüyor?
DigitalRoss

5
Birisi bu clipyöntemi Ruby topluluğuna nasıl gönderir ? Bunun gerçekten orada olması gerektiğini düşünüyorum ve maymun yaması Yanlış Şey .
Droogans

7
a.reverse.drop(1).reverseStratejiyi seviyorum . ;-)
Alex

92

Meraktan, neden sevmiyorsun a[0...-1]? Dizinin bir dilimini almak istiyorsunuz, böylece dilim işleci deyimsel bir seçim gibi görünüyor.

Ancak bunu her yerde çağırmanız gerekiyorsa, Array sınıfına DigitalRoss'un önerdiği gibi her zaman daha kolay bir ada sahip bir yöntem ekleme seçeneğiniz vardır. Belki de şöyle:

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

damla çok temiz olduğunda, sadece bir sürü dağınıklık gibi görünüyor. bu büyük bir sorun değil, kısa bir bakışta tam olarak doğru olduğunu teyit etmek zor. Adını tercih ederim drop_last, bu arada ...
Peter

-1 kullanmayı çok seviyorum .length kullanmaktan çok daha zarif
Will Nathan

Merak ediyorum, üçüncüsünün anlamı .nedir?
Joshua Pinter

5
... son öğeyi içermeyen anlamına gelir, -1 ise son öğedir. İki nokta yaparsanız, son öğeyi, üç noktayı içerecekse, son öğeyi içermez.
ckim

Dizinin kuyruğunu almak için dilim operatörünü kullanırken dikkatli olun: geri dönebilir nil: [][1..-1]-> nil, [][0...-1]->[]
Michael

57

Başka bir harika hile

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

Güzel, Ruby'nin buna sahip olduğunun farkında değildi; Bu yüzden a, *b = [1,2,3]diziye klasik bir araba / cdr tarzında bakalım.
Nobbynob Littlun

Dürüst olmak gerekirse, bu yorumu yazdığımı bile hatırlamıyorum: D şimdi sildi ...
Petr Bela

Çok basit ve güzel. THX
microspino

43

Bir pop()dizide bir işlem gerçekleştirmek istiyorsanız (son silinen öğenin silinmesine neden olur), ancak açılan bir öğe yerine diziyi elde etmekle ilgileniyorsanız şunları kullanabilirsiniz tap(&:pop):

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

Bu cevap anlamsal olarak bu kullanıcı için en anlamlı cevaptır. Ayna işlemleri elinizin altındadır ve yorumlaması kolay ve özlü kelimeler kullanır.
Jerome

2
Bu biraz kaygan Ruby.
emptywalls

38

Bunu şöyle yaparım:

my_array[0..-2]

2
Bu fevkalade çalışır. Neden çok daha karmaşık cevaplar olduğu konusunda kafam karıştı. Bu yeni bir Ruby eki mi?
Joshua Pinter

@JoshuaPinter en başından beri orada . Bunun en iyi yaklaşım olduğuna katılıyorum.
Julien

23

Damla yönteminin kendisini arttırmaya ne dersiniz, örneğin böyle?

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

Ardından, öğeleri sondan kaldırmak için negatif bir boyut kullanabilirsiniz, şöyle:

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

19

a[0...-1]en iyi yol gibi görünüyor. Dizi dilimleme sözdizimi tam olarak bu amaçla oluşturuldu ...

Alternatif olarak, diziyi yerinde değiştirmenin sakıncası yoksa, sadece şunu arayabilirsiniz a.pop:

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

daha sonra kullanmak üzere bir değişkene son elemanı da atayabilirsiniz:b = a.pop
Viktor Fonic

12

Son elemandan bir satırda geri kalanı geri dönmek için

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

Cidden olsa da,

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

11

Bu şekilde:

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

Ancak bunun nasıl çalıştığını açıklayalım:

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

Sonraki örnek, 0 konumdan sonuncuya kadar tüm kayıtları döndürür

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

Sonraki örnek kayıtları 1 konumdan sonuncuya döndürür

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

Ve burada ihtiyacınız olan şey var. Sonraki örnek, kayıtları 0 konumundan son 1'e döndürür

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

1
Bunun -2yerine yazabilirsiniz -1-1.
bfontaine

Yapabilir a[0...-1](3. noktayı fark edip) ve aynı sonucu alabilirsiniz a[0..-1-1], çünkü üçüncü nokta bitiş elemanını hariç tutmasını söyler. Bkz bu fazla ayrıntı için.
Julien

7

"Al" denediniz mi

a.take(3) 

6
genel olarak, bu a.take(a.size - 1); evet, bu seçeneği düşündüm.
Peter

2

Cevap: a.τwτ ama önce Pyper'ı yüklemelisin ...

Pyper intro: Lispy'ı biliyor carve dizinin cdr"ilk" ve "geri kalanını" döndürüyor musunuz ? Sadece seninki gibi ihtiyaçlar için, bu Lispy mekanizmasının bir uzantısını yaptım. Denir pyperve aynı zamanda 2., 2., 3., dinlenme, 3d ve son olarak, son vb. Hariç her şeye erişmenizi sağlar. caar, cadr, cdadarvb Lisp'te bilinmektedir:

# 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)

ve son olarak, sorunuzun cevabı:

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

Fazlası var:

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

bileşimler:

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

Orada sadece daha komut karakterler de vardır a..f, u..zve 0..9en önemlisi, mharita, yani:

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

Ancak diğer komut karakterleri çok sıcak ve şu anda kullanımı çok kolay değil.


1
Bunu 1 Nisan'da okuyorum, bu yüzden bunun bir şaka olduğunu varsaydım ... hayır. Bu şeyin Ruby için var olduğunu bilmiyordum. :)
Joshua Pinter

1

Bu, orijinalin son öğeleri hariç tümü ile yeni bir dizi oluşturur:

ary2 = ary.dup
ary2.pop

Birkaç kişinin #pop kullanılmasını önerdiğini unutmayın. Diziyi yerinde değiştirmeye hazırsanız, sorun değil. Bununla sorun olmazsa, önce bu örnekte olduğu gibi diziyi çoğaltın.


1
Diziyi değiştirmeyi tamamlarsanız, birkaç kişi #pop kullanmanızı önerir. Bununla sorun olmazsa, önce bu örnekte olduğu gibi diziyi çoğaltın.
alegscogs

Bu önemli bir yorum. Sadece cevabınıza da ekleyebilirsiniz. #Pop'un bir patlaması (!) Olmadığından, orijinal diziyi değiştirdiği gerçeği insanlardan kaçabilir.
mjnissim

Dizi büyükse bu şekilde verimsiz olur.
juliangonzalez

1

Sık sık kendimi bir dizinin son n öğesi dışında hepsini isterken bulurum. Bunu diğer çözümlerden daha okunabilir bir şekilde bulabilmek için kendi işlevimi geliştirdim:

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

Şimdi aşağıdakileri yapabilirsiniz:

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 için kasıtlı olarak izin verdim, böylece arayan bu yöntemi nasıl kullandıklarından sorumludur. Bu yaklaşımın yorumlarını / eleştirilerini duymak isterim.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.