Поради щодо гольфу в Рубі


62

Які загальні поради щодо гольфу в Рубі?

Я шукаю ідеї, які можна застосувати для кодування проблем із гольфом загалом, характерних для Рубі. (Наприклад, "Видалити коментарі" не буде відповіддю.)

Будь ласка, опублікуйте одну пораду на відповідь.


Комусь потрібно написати мову під назвою Rub, яка використовує один символ Unicode для кожного лексеми Ruby, начебто Jelly і Pyth :)
Марк Томас

Відповіді:


46
  • Числа 100 до 126 можна записати в вигляді ?dдо ?~1.8.
  • На подібній ноті, якщо вам потрібна односимвольна рядок у 1.9? X, коротше "x".
  • Якщо вам потрібно надрукувати рядок, не додаючи новий рядок, $><<"string"це коротше, ніж print"string".
  • Якщо вам потрібно прочитати кілька рядків, введення $<.map{|l|...}коротше, ніж while l=gets;...;end. Також ви можете використовувати, $<.readщоб прочитати все це відразу.
  • Якщо ви маєте читати з файлу $<і getsчитатимете його з файлу замість stdin, якщо ім'я файлу ввімкнено ARGV. Таким чином, golfiest спосіб переопісать catбуде: $><<$<.read.

1
? x дає код ascii в цілому, тож ви можете реально змусити всі друковані цифри розряджатися двома символами. 1.9 відрізняється, 'a'.ord дає число ascii, але на чотири байти довше десяткової версії.
Hiato

8
Рівним способом реалізації гравця catє залишити файл рубіну повністю порожнім (0 байт) і наполягати на тому, що його слід запускати з командного рядка з -pпрапором.
daniero

1
або, з власної відповіді @ daniero ,puts *$<
Не те, що Чарльз

1
Отже, у 1.8, все, що мені потрібно зробити, це піти? ~ І повернеться 126?
Просто красиве мистецтво

5
Ви можете вийти за межі 126 , використовуючи думає , як або , або , якщо ви досить божевільний:?﷽.ord=65021
Просто красива Art

32

Використовуйте оператор splat, щоб отримати хвіст і голову масиву:

head, *tail = [1,2,3]
head => 1
tail => [2,3]

Це також працює в інший спосіб:

*head, tail = [1,2,3]
head => [1,2]
tail => 3

Використовуйте *метод з рядком на масиві для приєднання елементів:

[1,2,3]*?,
=> "1,2,3"

27
  • Використовуйте abortдля завершення програми та надрукування рядка в STDERR - коротше, ніж putsслідexit
  • Якщо ви читаєте рядок з gets, ви можете використовувати його ~/$/для пошуку довжини (це не враховує зворотний новий рядок, якщо він існує)
  • Використовуйте []для перевірки, чи містить рядок інше:'foo'['f'] #=> 'f'
  • Використовуйте trзамість gsubзаміни символів:'01011'.tr('01','AB') #=> 'ABABB'
  • Якщо вам потрібно вилучити нові рядки, використовуйте chopзамістьchomp

2
+1 для abortта~/$/
J -_- L

Поясніть, будь ласка, як користуватися~/$/
Mathieu CAROFF

@MathieuCAROFF кожного разу, коли ви телефонуєте gets, його результат зберігається у $_змінній. /regex/ ~= stringповертає індекс першого збігу. Виклик ~у регулярному виразі еквівалентний /regex/ ~= $_. Так це було б щось на зразокs=gets;l= ~/$/
Cyoce

20

Закінчіть своє end.

Спробуйте видалити endзі свого коду.

Не використовуйте def...endдля визначення функцій. Зробіть лямбда з новим оператором -> в Ruby 1.9. (Оператор -> - "лямбда", або "ракета",. Це дозволяє економити 5 символів на функцію.

# 28 characters
def c n
/(\d)\1/=~n.to_s
end

# 23 characters, saves 5
c=->n{/(\d)\1/=~n.to_s}

Виклики методів є c nабо c(n). Дзвінки лямбда є c[n]. Змінюючи один c nна c[n]витрати 1 символ, так що якщо ви можете використовувати c nбільш ніж в 5 разів, а потім зберегти цей метод.

Усі методи, які беруть do...endблоки, можуть {...}замість цього приймати блоки. Це економить від 3 до 5 символів. Якщо пріоритет {...}занадто високий, використовуйте дужки, щоб виправити це.

# 48 characters
(?a..?m).zip (1..5).cycle do|a|puts a.join','end

# WRONG: passes block to cycle, not zip
(?a..?m).zip (1..5).cycle{|a|puts a.join','}

# 45 characters, saves 3
(?a..?m).zip((1..5).cycle){|a|puts a.join','}

Замініть if...else...endна потрійного оператора ?: . Якщо у відділення є два або більше висловлювань, загорніть їх у дужки.

# 67 characters
if a<b
puts'statement 1'
puts'statement 2'else
puts'statement 3'end

# 62 characters, saves 5
a<b ?(puts'statement 1'
puts'statement 2'):(puts'statement 3')

У вас, ймовірно, немає whileабо untilциклів, але якщо ви це зробите, то запишіть їх у формі модифікатора.

(a+=1
b-=1)while a<b

Чи потрібні круглі дужки puts'statement 3'?
Кіос

15

Додавання до w0lf

Під час роботи з масивами .compactможна замінити -[nil]на збереження 2 символів.

У поєднанні з вище -> ви можете зробити його ще коротшим, -[p]щоб зберегти ще два символи.


14

Використовуйте короткі заздалегідь задані змінні, де це можливо, наприклад $*замість ARGV. Там хороший список з них тут , поряд з великою кількістю іншої корисної інформації.


12

Коли ви використовуєте рядкову інтерполяцію (як слід додати публікацію Мартина Бюттнера ), вам не потрібні фігурні дужки, якщо на вашому об'єкті є сигіл ( $, @) перед ним. Корисно для магічних змінних , таких як $_, $&, і $1т.д .:

puts "this program has read #$. lines of input"

Отже, якщо вам потрібно буде надрукувати змінну більше, ніж ви використовуєте її в іншому випадку, ви можете зберегти кілька байт.

a=42; puts "here is a: #{a}"; puts "here is a again: #{a}"
$b=43; puts "here is b: #$b"; puts "here is b again: #$b"

11

Якщо вам потрібно знайти, чи певний елемент eзнаходиться в межах діапазону r, ви можете використовувати

r===e

замість довшого:

r.cover?(e) # only works if `r.exclude_end?` is false

або

r.member?(e)

або

r.include?(e)

3
Ще не r===eкоротше?
акун

@akuhn Так, так. Набагато коротше. Дякуємо, що вказали
Крістіан Лупаску

1
Ласкаво просимо. Все, що може бути використано в операторі комутатора, ===реалізовано.
акун

10

$_ є останнім прочитаним рядком.

  • print - якщо не вказано аргумент вмісту друку $_
  • ~/regexp/ - короткий для $_=~/regexp/

У Ruby 1.8 у вас є чотири методи, Kernelякі працюють на $_:

  • chop
  • chomp
  • sub
  • gsub

У Ruby 1.9 ці чотири методи існують лише у тому випадку, якщо ваш сценарій використовує -nабо -p.

Якщо ви хочете часто друкувати якусь змінну, тоді використовуйте trace_var(:var_name){|a|p a}


2
Вони доступні лише під час запуску Ruby з опцією -pабо -n. Довідково.
Даррен Стоун

1
Здається, trace_varпрацює лише із глобальними змінними $
daniero

10

Використовуйте строкову інтерполяцію!

  1. Для заміни to_s. Якщо вам потрібні дужки навколо того, що ви хочете перетворити на рядок, to_sце два байти довше інтерполяції рядків:

    (n+10**i).to_s
    "#{n+10**i}"
    
  2. Щоб замінити конкатенацію. Якщо ви об'єднаєте щось, оточене двома іншими рядками, інтерполяція може врятувати вас один байт:

    "foo"+c+"bar"
    "foo#{c}bar"
    

    Також працює, якщо середня річ сама є об'єднаною, якщо просто перемістити конкатенацію всередині інтерполяції (замість того, щоб використовувати кілька інтерполяцій):

    "foo"+c+d+e+"bar"
    "foo#{c+d+e}bar"
    

10

Уникайте lengthвif a.length<n

lengthце 6 байт, трохи дорогий у коді гольф. у багатьох ситуаціях ви можете замість цього перевірити, чи є в масиві що-небудь в заданій точці. якщо ви перейдете останній індекс, який ви отримаєте nil, значення фальси.

Отже ви можете змінити:

if a.length<5до if !a[4]-5 байт

або

if a.length>5до if a[5]-6 байт

або

if a.length<nдо if !a[n-1]-3 байт

або

if a.length>nдо if a[n]-6 байт

Примітка : працюватиме лише з масивом усіх правдоподібних значень. наявність масиву nilабо falseв ньому може спричинити проблеми.


4
Я завжди використовую size… Але це, безумовно, краще. До речі, Stringтеж працює .
манатура

10

Не використовуйте ключові слова trueта false.

Використання:

  • !pза true(дякую, гістократе!)
  • !0для false. Якщо все, що вам потрібно, - це помилкове значення, то ви можете просто використовувати p(що повертається nil).

щоб зберегти деякі символи.


1
Якщо ви насправді не потребуєте true(тобто, якщо триєтажних значень недостатньо, як, наприклад, в умовах if), вам навіть це не потрібно !!.
Мартін Ендер

4
І так само p(що оцінює nil) - це коротше значення фальси. Що означає найкоротший шлях - trueце !p.
гістократ

@histocrat хороший пункт! Я відредагував свою відповідь.
Крістіан Лупаску


9

Якщо ви коли - небудь знадобиться , щоб отримати число від ARGV, getабо що - щось подібне зробити що - то , що багато разів, замість виклику to_iна нього, ви можете просто використовувати , ?1.upto x{do something x times}де х є рядком.

Таким чином, використовуючи ?1.upto(a){}замість, x.to_i.times{}ви заощадите 2 символи.

Ви також можете переписати такі речі, як p 1 while 1або p 1 if 1як p 1while 1абоp 1if 1

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

Крім того, якщо вам потрібно призначити перший елемент масиву змінній, a,=cзбережете два символи на відміну відa=c[0]


9

Нові функції в Ruby 2.3 і 2.4

Добре бути в курсі нових мовних особливостей, які допоможуть вашій грі в гольф. В останніх рубінах є кілька чудових.

Рубін 2.3

Оператор безпечної навігації: &.

Коли ви викликаєте метод, який може повернутися, nilале ви хочете пов'язати додаткові виклики методу, якщо це не так, ви витрачаєте байти, обробляючи цей nilвипадок:

arr = ["zero", "one", "two"]
x = arr[5].size
# => NoMethodError: undefined method `size' for nil:NilClass

x = arr[5].size rescue 0
# => 0

"Оператор безпечної навігації" зупиняє ланцюжок викликів методу, якщо повертається nilта повертається nilдля цілого виразу:

x = arr[5]&.size || 0
# => 0

Array#dig & Hash#dig

Глибокий доступ до вкладених елементів, з приємною короткою назвою:

o = { foo: [{ bar: ["baz", "qux"] }] }
o.dig(:foo, 0, :bar, 1) # => "qux"

Повертається, nilякщо він потрапив у глухий кут:

o.dig(:foo, 99, :bar, 1) # => nil

Enumerable#grep_v

Зворотний - Enumerable#grepповертає всі елементи, які не відповідають заданому аргументу (порівняно з ===). Мовляв grep, якщо вказано блок, його результат повертається замість цього.

(1..10).grep_v 2..5 # => [1, 6, 7, 8, 9, 10]
(1..10).grep_v(2..5){|v|v*2} # => [2, 12, 14, 16, 18, 20]

Hash#to_proc

Повертає Proc, який дає значення для даного ключа, що може бути досить зручно:

h = { N: 0, E: 1, S: 2, W: 3 }
%i[N N E S E S W].map(&h)
# => [0, 0, 1, 2, 1, 2, 3]

Рубін 2.4

Ruby 2.4 ще не вийшов, але це скоро, і він має деякі чудові функції. (Коли вона вийде, я оновлю цю публікацію з деякими посиланнями на документи.) Про більшість із них я дізнався у цій чудовій публікації в блозі .

Enumerable#sum

Не більше arr.reduce(:+). Тепер ви можете просто зробити arr.sum. Він приймає необов'язковий аргумент початкового значення, який за нульовими елементами ( [].sum == 0) за замовчуванням дорівнює 0 . Для інших типів потрібно вказати початкове значення. Він також приймає блок, який буде застосовано до кожного елемента перед додаванням:

[[1, 10], [2, 20], [3, 30]].sum {|a,b| a + b }
# => 66

Integer#digits

Це повертає масив цифр числа у порядку найменшого значення:

123.digits # => [3, 2, 1]

У порівнянні, скажімо 123.to_s.chars.map(&:to_i).reverse, це досить приємно.

Як бонус він приймає необов'язковий аргумент:

a = 0x7b.digits(16) # => [11, 7]
a.map{|d|"%x"%d} # => ["b", "7"]

Comparable#clamp

Робить те, що написано на бляшанці:

v = 15
v.clamp(10, 20) # => 15
v.clamp(0, 10) # => 10
v.clamp(20, 30) # => 20

Оскільки він є у Порівнянні, ви можете використовувати його з будь-яким класом, що включає Порівняльний, наприклад:

?~.clamp(?A, ?Z) # => "Z"

String#unpack1

2-байт економія понад .unpack(...)[0]:

"👻💩".unpack(?U)    # => [128123]
"👻💩".unpack(?U)[0] # => 128123
"👻💩".unpack1(?U)   # => 128123

Точність аргумент Numeric#ceil, floorіtruncate

Math::E.ceil(1) # => 2.8
Math::E.floor(1) # => 2.7
(-Math::E).truncate(1) # => -2.7

Багаторазове призначення в умовних умовах

Це спричиняє помилку в попередніх версіях Ruby, але допускається в 2.4.

(a,b=1,2) ? "yes" : "no" # => "yes"
(a,b=nil) ? "yes" : "no" # => "no"

Гольф Math::E.ceil(1)до Math::E.ceil 1, а також для floorі truncate.
Просто красиве мистецтво

1
@SimplyBeautifulArt Я сподіваюсь, що хтось із гольфу в Рубі зможе зробити цей стрибок самі.
Йорданія

Бо Enumerable#sum, .flatten.sumна 2 байти коротше, ніж.sum{|a,b|a+b}
Асона Тухід

(-Math::E).truncate(1)еквівалентна на -Math::E.truncate(1)1 байт коротше
Асона Тухід

1
&.можна використовувати з такою підпискою a&.[]i(на 1 байт коротше, ніж a&.at i). Хоча, якщо потрібні дужки, a||a[i]на 1 байт коротше a&.[](i)абоa&.at(i)
Асона Тухід

7

Наукові позначення часто можна використовувати для гоління знаків або двох:

x=1000
#versus
x=1e3

9
Примітка. Це поверне значення Float (1000,0) замість цілого числа, що може призвести до неточних результатів з великою кількістю.
Догберт

4
Ах, приємно 1e2краще, ніж 100.0коли потрібен відсоток.
Фрогз

Схожий на цей принцип, 1.0*на 1 char коротший, ніж.to_f
Unihedron

7

Використовуйте операторні методи замість дужок

Скажімо, ви хочете висловитись a*(b+c). Через перевагу a*b+c(очевидно) не вийде. Класний спосіб використання операторів Рубі на допомогу приходить на допомогу! Ви можете використовувати , a.*b+cщоб зробити пріоритет з *нижче , ніж у +.

a*(b+c) # too long
a*b+c   # wrong
a.*b+c  # 1 byte saved!

Це може також працювати з !і ~операторами ( такими речами , як унарні +або унарний -не працює , тому що їх методи -@і +@, економлячи , ()але додавання .@)

(~x).to_s # too long
~x.to_s   # error
x.~.to_s  # 1 byte saved!

6

Використовуйте ||замість цього orі &&замість цього and.

Поруч із одним символом andви можете зберегти пробіли (а може бути і дужку) навколо оператора.

p true and false ? 'yes' :'no'   #-> true (wrong result)
p (true and false) ? 'yes' :'no' #-> 'no'
p true&&false ? 'yes' :'no'      #-> 'no', saved 5 characters


p true or false ? 'yes' :'no'   #-> true (wrong result)
p (true or false) ? 'yes' :'no' #-> 'yes'
p true||false ? 'yes' :'no'      #-> 'yes', saved 4 characters

Якщо ви цикли на масиві, який ви зазвичай використовуєте each. Але mapпетлі також над масивом, і він на один символ коротший.


6

Я просто спробував TDD код-гольф виклик, тобто написати найкоротший код, щоб передати характеристики. Технічні характеристики були щось подібне

describe PigLatin do
  describe '.translate' do
    it 'translates "cat" to "atcay"' do
      expect(PigLatin.translate('cat')).to eq('atcay')
    end
    # And similar examples for .translate
  end
end

Заради коду-гольфу не потрібно створювати модуль чи клас.

Замість

module PigLatin def self.translate s;'some code'end;end

можна зробити

def(PigLatin=p).translate s;'some code'end

Зберігає 13 символів!


7
Ха, дуже ретельно. Мало того, що ви додали необхідну поведінку до PigLatin, а й @pig_latin, $pig_latinі 'pig'['latin'].
гістократ

@histocrat: Зараз я зрозумів. Це тому, translateщо було визначено на nil.
Ерік Думініл

6

Ядро # p - цікавий метод.

Використовуйте p varзамість puts var. Це чудово працює з цілими числами та плавцями, але не з усіма типами. Він друкує лапки навколо рядків, що, мабуть, не те, що потрібно.

Використовується з одним аргументом, pповертає аргумент після його друку.

Використовується з кількома аргументами, pповертає аргументи в масив.

Використовуйте p(без аргументів) замість nil.


10
На жаль, p 'some string'друкує "some string"і не тільки те, some stringщо часто критикується іншими.
Патрік Осіті

1
В основному p sте саме puts s.inspect, але повертаєтьсяs
Cyoce

6

Не використовуйте #each. Ви можете просто перекинути всі елементи за допомогою #map. Так замість

ARGV.each{|x|puts x}

ви можете зробити те ж саме в менших байтах.

ARGV.map{|x|puts x}

Звичайно, у цьому випадку puts $*було б ще коротше.


Існують букви для раціональних і складних чисел:

puts 3/11r == Rational(3,11)
puts 3.3r == Rational(66,20)
puts 1-1.i == Complex(1,-1)

=> true
true
true

Ви можете використовувати більшість байтів у рядках. "\x01"(6 байт) можна скоротити до ""(3 байти). Якщо вам потрібен лише цей один байт, це можна скоротити ще більше ?(2 байти).

Таким же чином, ви можете отримати нові рядки, такі як:

(0..10).to_a.join'
'

 => "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10"

Ви можете використовувати ?\nі те ?\t, що на один байт коротше "\n"і "\t". Для обтурації також є пробіл?


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

A=C+B=7+C=9

=> A=17, B=16, C=9

Це коротше C=9;B=16;A=17або C=0;B=C+7;A=C+B.


Якщо вам потрібна нескінченна петля, використовуйте loop{...}. Петлі невідомої довжини можуть бути коротшими з іншими петлями:

loop{break if'
'==f(gets)}

while'
'!=f(gets);end

Ще кілька хитрощів gsub / regexp. Використовуйте спеціальні '\1'символи втечі замість блоку:

"golf=great short=awesome".gsub(/(\w+)=(\w+)/,'(\1~>\2)')

"golf=great short=awesome".gsub(/(\w+)=(\w+)/){"(#{$1}~>#{$2})")

І спеціальні змінні $1тощо, якщо вам потрібно виконати операції. Майте на увазі, що вони визначені не тільки всередині блоку:

"A code-golf challenge." =~ /(\w+)-(\w+)/
p [$1,$2,$`,$']

=> ["code", "golf", "A ", " challenge."] 

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

x+=1if$*<<A==????::??==??

"Будь ласка, опублікуйте одну пораду за відповідь." Також ?\nприємно, але насправді не коротше, ніж насправді введення символів нового рядка в лапки. (те саме для вкладки)
Мартін Ендер

І puts$*ще коротше.
Кіос

Я знаю, що ви намагалися довести свою точку, але я майже впевнений, що останній приклад такий самий, якx+=1;$*<<A
Асона Тухід

6

Ще один спосіб використання оператора splat: якщо ви хочете призначити один літеральний масив, a *з лівого боку коротше дужок з правого боку:

a=[0]
*a=0

З кількома значеннями вам навіть не потрібен оператор splat (дякує гістократу за те, що мене виправляв):

a=[1,2]
a=1,2

Останній випадок насправді не потрібен.
гістократ

@histocrat О, уау, я думав, що друге значення буде просто відкинуто в такому випадку.
Мартін Ендер

1
Я не можу повірити, що я цього не знав увесь час, коли я проводив гольф у Рубі.
Дверна ручка

6

Коли виклик вимагає вивести кілька рядків, вам не доведеться прокручувати результати, щоб надрукувати кожен рядок, наприклад, масив. putsМетод буде вирівнюватися масив і роздрукувати кожен елемент в окремому рядку.

> a = %w(testing one two three)
> puts a
testing
one
two
three

Поєднавши оператора бризки, #pви можете зробити його ще коротшим:

p *a

Оператор splat (технічно це *@метод, я думаю) також передає ваші масиви без масиву до масивів:

> p a.lazy.map{|x|x*2}
#<Enumerator::Lazy: #<Enumerator::Lazy: [1, 2, 3]>:map>

проти

> p *a.lazy.map{|x|x*2}
2
4
6

1
*@не є методом, splat є синтаксичним цукром
Asone Tuhid

6

Збережіть кілька байт під час видалення повторних елементів масиву

a.uniq # before
a|[]   # after
    ^^

Якщо ви будете використовувати порожній масив []у змінній, ви можете зберегти ще більше байтів:

a.uniq;b=[] # before
a|b=[]      # after
      ^^^^^

2
У першому випадку a&a- на 1 байт коротше
Асона Тухід

5

Використовуйте Goruby замість Ruby, що є чимось на зразок скороченої версії Ruby. Ви можете встановити його за допомогою rvm via

rvm install goruby

Goruby дозволяє писати більшу частину коду так, як ви писали б Ruby, але вбудовані додаткові абревіатури. Щоб дізнатися про найкоротший доступний абревіатуру для чогось, ви можете скористатися допоміжним методом shortest_abbreviation, наприклад:

shortest_abbreviation :puts
#=> "pts"

Array.new.shortest_abbreviation :map
#=> "m"

String.new.shortest_abbreviation :capitalize
#=> "cp"

Array.new.shortest_abbreviation :join
#=> "j"

Також дуже зручним є псевдонім, sayдля putsякого і сам його можна скоротити s. Так замість

puts [*?a..?z].map(&:capitalize).join

тепер можна писати

s [*?a..?z].m(&:cp).j

друкувати алфавіт великими літерами (що не є хорошим прикладом). У цьому дописі в блозі пояснюється більше матеріалів та деяких внутрішніх робіт, якщо ви зацікавлені у подальшому читанні.

PS: не пропустіть hметод ;-)


Більше ніж через 2 роки, і я нарешті з’ясував, про що мені нагадує ця відповідь ...
undergroundmonorail

5

Щоб приєднатись до масиву замість цього

[...].join

зробити це

[...]*''

що зберігає 2 байти. Для приєднання з роздільником використовуйте

[...]*?,

5

Підписка номерів!

Я щойно відкрив це вчора. n[i]повертає nбіт на i-му позицію. Приклад:

irb(main):001:0> n = 0b11010010
=> 210
irb(main):002:0> n[0]
=> 0
irb(main):003:0> n[1]
=> 1
irb(main):004:0> n[2]
=> 0
irb(main):005:0> n[3]
=> 0
irb(main):006:0> n[4]
=> 1
irb(main):007:0> n[5]
=> 0

А тепер ви можете використовувати більше аргументів, таких якn[0..3]
Просто красиве мистецтво

4

Можливо, ви зможете зберегти 2 символи та використовувати

[*(...)]

замість

(...).to_a

Наприклад, припустимо, у нас є діапазон, який ми хочемо як масив:

(1..2000).to_a

Просто роби це так:

[*1..2000]  #  Parentheses around the (ran..ge) is not needed!

А тепер у вас є масив як масив.


5
Я думаю [*1..2000], теж працює?
Лінн

4

<< хитрість

a.push x

можна скоротити до:

a<<x

для -4 байт.


2
Примітка. Це також працює для Strings
Cyoce

4

Array#assoc/rassoc

Коли у вас є масив масивів і ви хочете знайти підмасив, який починається з певного значення, не Enumerable#findвикористовуйте Array#assoc:

a = [[0,"foo"],[0,"bar"],[1,"baz"],[0,"qux"]]
a.find{|x,|x==1} # => [1,"baz"]
a.assoc(1) # => [1,"baz"]

Це також є хорошою заміною для Enumerable#any?деяких ситуацій.

Array#rassoc робить те ж саме, але перевіряє останній елемент підмасивів:

a = [[123,"good"],[456,"good"]]
a.any?{|*,x|x=="bad"} # => false
a.rassoc("bad") # => nil

Для a.any?рядка в rassoc прикладі, що |x,|робити? Чим він відрізняється від |x|?
Cyoce

@Cyoce Параметр блоку деструктурірующій слід тим же правилам, що і призначення знищення того , так як x=[1,2]проти x,=[1,2]. Використовуючи мій приклад вище, з |x|, в першій ітерації xбуде [0,"foo"]. З |x,y|, xбуде 0і yбуде "foo". Так само, з |x,|, xбуде 0. Іншими словами, в ньому сказано: "покладіть перший елемент xі відкиньте решту"
Йорданія

Зауважте, що це не працює в зворотному порядку, наприклад |,y|, це SyntaxError, ergo |_,y|. Але я тільки що зрозумів, що |*,y|працює, що чистіше, ніж використання змінної з назвою _(але не коротшої).
Йорданія
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.