Весь останній елемент масиву 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:
a.τaτ #=> "lorem"
a.τdτ #=> ["ipsum", "dolor", "sit", "amet"]
a.τbτ #=> "ipsum"
a.τeτ #=> ["dolor", "sit", "amet"]
a.τcτ #=> "dolor" (3rd)
a.τzτ #=> "amet" (last)
a.τyτ #=> "sit" (2nd from the end)
a.τxτ #=> "dolor" (3rd from the end)

і нарешті, відповідь на ваше запитання:

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

Є ще:

a.τuτ #=> ["lorem", "ipsum", "dolor"] (all except last 2)
a.τ1τ #=> ["lorem", "ipsum"] (first 2)
a.τ8τ #=> (last 2)
a.τ7τ #=> (last 3)

Склади:

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

Також є більше командних символів, ніж просто a..f, u..zі 0..9, головне m, означає карту:

a.τwmbτ #=> ["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.