Весь останній елемент масиву 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,9, а не рубін 1,8,6
Ендрю Грімм

Як щодо вистави? Якби я використовував ці відповіді в ітераціях тисячі разів .. який би виграв?
Ninad

Іншими словами, яке рішення не проходить масив під кришкою?
Нінад

інший спосіб, a - ([a.size])
Іоанн

Відповіді:


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

Це цікаво, я задумався, наскільки це поширене. Що думають люди про режим поезії?
DigitalRoss

5
Як хтось подає цей clipметод спільноті Ruby? Я дійсно думаю, що це повинно бути там, і мавпа-латання - це неправильна річ .
Droogans

7
Мені подобається a.reverse.drop(1).reverseстратегія. ;-)
Олексій

92

З цікавості, чому ти не любиш a[0...-1]? Ви хочете отримати фрагмент масиву, тому оператор зрізів здається ідіоматичним вибором.

Але якщо вам потрібно зателефонувати цьому всюди, у вас завжди є можливість додати метод з більш привітним іменем до класу Array, як це запропонував DigitalRoss. Можливо, так:

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

Це просто здається великим безладом, коли крапля така чиста. це не велика справа, але важко короткий погляд підтвердити, що це абсолютно правильно. Я вважаю за краще ваше ім’я, drop_lastдо речі ...
Пітер

Я люблю використовувати -1 настільки елегантніше, ніж використовувати .length
Буде Натан,

Цікаво, у чому сенс цієї третини .?
Джошуа Пінтер

5
... означає не включати останній елемент, -1 - останній елемент. Якщо ви зробили дві крапки, то він буде включати останній елемент, три крапки, тоді він не буде включати останній елемент.
ckim

Будьте обережні, використовуючи оператор зрізів, щоб отримати хвіст масиву: він може повернутися nil: [][1..-1]-> nil, [][0...-1]->[]
Майкл

57

Ще один крутий трюк

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

Ніцца, не знав, що Рубі це мав; тож a, *b = [1,2,3]давайте подивимось на масив класичним способом автомобіля / компакт-диска.
Nobbynob Littlun

Чесно кажучи, я навіть не пам'ятаю, щоб писати цей коментар: D видалив його зараз ...
Петро Бела

Soooo простий і приємний. THX
мікроспіно

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
Це якась струнка Рубі.
порожні стіни


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
Віктор Фоніч

12

Щоб позбутися останнього елемента в одному рядку, а решта повертається

[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

Ви можете зробити це a[0...-1](помітити 3-ю крапку) і отримати той же результат a[0..-1-1], що і тому, що третя крапка каже йому виключати закінчуючий елемент. Дивіться це для більш детальної інформації.
Жульєн


2

Відповідь: a.τwτ але вам потрібно спочатку встановити Pyper ...

Піпер вступ: Ви знаєте Ліспі carі cdrповертаєте "перший" і "відпочинок" масиву? Тільки для потреб, як ваша, я зробив розширення цього механізму Ліспі. Він називається pyper, і він дозволяє вам отримати доступ також до 2-го, відпочинок від 2-го, 3-го, відпочинок від 3d, а також останній, все, крім останнього тощо. Про це було б не багато про що писати, але він також дозволяє складати літери, як і caar, cadr, і cdadarт.д. відомо з 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..f, u..zі 0..9, головне m, означає карту:

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

Але інші символи команди занадто гарячі і не дуже прості у використанні на даний момент.


1
Я читаю це 1 квітня, тому припустив, що це жарт ... ні. Не мав уявлення, що цей матеріал існує для Рубі. :)
Джошуа Пінтер

1

Це робить новий масив з усіма елементами оригіналу, крім останніх:

ary2 = ary.dup
ary2.pop

Зауважте, що кілька інших запропонували використовувати #pop. Якщо ви все добре змінюєте масив на місці, це добре. Якщо з цим все не в порядку, спочатку скопіюйте масив, як у цьому прикладі.


1
Кілька інших запропонували використовувати #pop, якщо ви добре змінюєте масив на місці. Якщо з цим все не в порядку, спочатку скопіюйте масив, як у цьому прикладі.
alegscogs

Це важливий коментар. Ви можете просто додати його до своєї відповіді. Оскільки у #pop немає удару (!), Той факт, що він модифікує вихідний масив, може уникнути людей.
mjnissim

Це неефективно, якщо масив великий.
juliangonzalez

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, щоб абонент відповідав за те, як вони використовують цей метод. Я хотів би почути коментарі / критику щодо цього підходу.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.