Tipps zum Golfen in Ruby


62

Welche allgemeinen Tipps können Sie zum Golfen in Ruby geben?

Ich bin auf der Suche nach Ideen, die sich auf Code-Golf-Probleme im Allgemeinen anwenden lassen, die speziell für Ruby gelten. (Zum Beispiel wäre "Kommentare entfernen" keine Antwort.)

Bitte posten Sie einen Tipp pro Antwort.


Jemand muss eine Sprache namens Rub schreiben, die für jedes Ruby-Token ein einzelnes Unicode-Zeichen verwendet, etwa Jelly und Pyth :)
Mark Thomas

Antworten:


46
  • Die Zahlen von 100 bis 126 kann geschrieben werden , ?dum ?~in 1.8.
  • In ähnlicher Weise ist x kürzer als "x", wenn Sie eine Zeichenfolge mit nur einem Zeichen in 1.9 benötigen.
  • Wenn Sie eine Zeichenfolge drucken müssen, ohne eine neue Zeile anzufügen, $><<"string"ist sie kürzer als print"string".
  • Wenn Sie mehrere Eingabezeilen lesen müssen, $<.map{|l|...}ist dies kürzer als while l=gets;...;end. Sie können auch verwenden $<.read, um alles auf einmal zu lesen.
  • Wenn Sie aus einer Datei lesen sollen $<und getsstatt stdin aus einer Datei lesen, wenn der Dateiname in ist ARGV. So ist die golfiest Weise neu zu implementieren catwäre: $><<$<.read.

1
? x gibt den ASCII-Code im Allgemeinen aus, sodass Sie alle Ausdrucke realistisch in Ziffern mit zwei Zeichen umwandeln können. 1.9 ist anders, 'a'.ord gibt die ASCII-Zahl an, ist aber vier Bytes länger als die Dezimalversion.
Hiato

8
Eine noch erfolgreichere Möglichkeit zur Implementierung catbesteht darin, die Ruby-Datei vollständig leer zu lassen (0 Byte) und darauf zu bestehen, dass sie über die Befehlszeile mit dem -pFlag ausgeführt wird.
Daniero

1
oder, aus @ danieros eigener Antwort ,puts *$<
Nicht dass Charles

1
Also in 1.8 muss ich nur gehen? ~ Und es wird 126 zurückkehren?
Simply Beautiful Art

5
Sie können über 126 hinausgehen, indem Sie denkt wie oder , oder wenn Sie verrückt genug sind:?﷽.ord=65021
Simply Beautiful Art

32

Verwenden Sie den splat-Operator, um den Schwanz und den Kopf eines Arrays zu erhalten:

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

Das funktioniert auch andersherum:

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

Verwenden Sie die *Methode mit einer Zeichenfolge in einem Array, um Elemente zu verbinden:

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

27
  • Beendet abortdas Programm und gibt einen String an STDERR aus - kürzer als putsgefolgt vonexit
  • Wenn Sie eine Zeile mit lesen gets, können Sie ~/$/ihre Länge ermitteln (dies zählt keine nachgestellte neue Zeile, falls vorhanden).
  • Verwenden Sie []diese Option , um zu überprüfen, ob eine Zeichenfolge eine andere enthält:'foo'['f'] #=> 'f'
  • Verwenden Sie transtelle von gsubfür zeichenweise Ersetzungen:'01011'.tr('01','AB') #=> 'ABABB'
  • Wenn Sie nachfolgende Zeilenumbrüche entfernen müssen, verwenden Sie chopanstelle vonchomp

2
+1 für abortund~/$/
J -_- L

Bitte erläutern Sie die Verwendung~/$/
Mathieu CAROFF

@MathieuCAROFF Bei jedem Aufruf getswird das Ergebnis in der $_Variablen gespeichert . /regex/ ~= stringGibt den Index der ersten Übereinstimmung zurück. Das Aufrufen ~eines regulären Ausdrucks entspricht /regex/ ~= $_. Also wäre es so etwas wies=gets;l= ~/$/
Cyoce

20

Beende deine end.

Versuchen Sie, endaus Ihrem Code zu entfernen .

Verwenden Sie nicht def...end, um Funktionen zu definieren. Machen Sie ein Lambda mit dem new -> Operator in Ruby 1.9. (Der Operator -> ist eine "Stabby-Lambda" - oder "Dash-Rakete" .) Dadurch werden 5 Zeichen pro Funktion gespeichert .

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

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

Methodenaufrufe sind c noder c(n). Lambda ruft an c[n]. Ändern jeder c nauf c[n]Kosten 1 Zeichen, so dass , wenn Sie verwenden können , c nmehr als 5 - mal, dann die Methode halten.

Alle Methoden, die do...endBlöcke annehmen , können {...}stattdessen Blöcke annehmen . Das spart 3 bis 5 Zeichen. Wenn die Priorität von {...}zu hoch ist, verwenden Sie Klammern, um sie zu beheben.

# 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','}

Ersetzen Sie if...else...enddurch den ternären Operator ?: . Wenn ein Zweig zwei oder mehr Anweisungen enthält, setzen Sie sie in Klammern.

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

Sie haben wahrscheinlich keine whileoder untilSchleifen, aber wenn Sie dies tun, schreiben Sie sie in Modifikatorform.

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

Sind die Klammern um puts'statement 3'notwendig?
Cyoce

15

Zusatz zu w0lf

.compactKann beim Arbeiten mit Arrays durch ersetzt werden -[nil], um 2 Zeichen zu sparen.

Kombiniert mit oben -> können Sie es mit noch kürzer machen -[p], um weitere 2 Zeichen zu sparen.


14

Verwenden Sie nach Möglichkeit die kurzen vordefinierten Variablen, z . B. $*anstelle von ARGV. Es gibt eine gute Liste von ihnen hier , zusammen mit vielen anderen nützlichen Informationen.


12

Wenn Sie die Zeichenfolgeninterpolation verwenden (wie Sie es bei Martin Büttners Beitrag tun sollten ), brauchen Sie die geschweiften Klammern nicht, wenn Ihr Objekt ein Siegel ( $, @) vor sich hat. Nützlich für magische Variablen wie $_, $&, $1etc:

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

Wenn Sie also eine Variable häufiger drucken müssen als sonst, können Sie einige Bytes sparen.

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

Wenn Sie feststellen müssen, ob sich ein bestimmtes Element ein einem Bereich befindet r, können Sie verwenden

r===e

statt der längeren:

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

oder

r.member?(e)

oder

r.include?(e)

3
Ist nicht r===enoch kürzer?
Akuhn

@akuhn Ja, das ist es. Viel kürzer. Vielen Dank für den Hinweis, dass es mir geholfen hat, meinen Code um 10 Zeichen zu verkürzen. Das ist riesig: codegolf.stackexchange.com/a/6125/3527
Cristian Lupascu

1
Bitte. Alles, was in einer switch-Anweisung verwendet werden kann, wurde ===implementiert.
Akuhn

10

$_ ist die zuletzt gelesene Zeile.

  • print - wenn kein Argument für den Druckinhalt von $_
  • ~/regexp/ - kurz für $_=~/regexp/

In Ruby 1.8 stehen Ihnen vier Methoden zur Verfügung Kernel, mit denen Sie arbeiten können $_:

  • chop
  • chomp
  • sub
  • gsub

In Ruby 1.9 gibt es diese vier Methoden nur, wenn Ihr Skript -noder verwendet -p.

Wenn Sie eine Variable häufig drucken möchten, verwenden Sie trace_var(:var_name){|a|p a}


2
Diese sind nur verfügbar, wenn Sie Ruby mit der Option -poder ausführen -n. Referenz.
Darren Stone

1
Es scheint, dass trace_varnur mit globalen $
-Variablen

10

Verwenden Sie die String-Interpolation!

  1. Zu ersetzen to_s. Wenn Sie Klammern benötigen, um eine Zeichenfolge zu erstellen, to_ssind diese zwei Byte länger als die Zeichenfolgeninterpolation:

    (n+10**i).to_s
    "#{n+10**i}"
    
  2. Verkettung ersetzen. Wenn Sie etwas verketten, das von zwei anderen Zeichenfolgen umgeben ist, können Sie durch Interpolation ein Byte sparen:

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

    Funktioniert auch, wenn das Mittelteil selbst verkettet ist, wenn Sie die Verkettung nur innerhalb der Interpolation verschieben (anstatt mehrere Interpolationen zu verwenden):

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

10

Vermeiden Sie lengthinif a.length<n

lengthist 6 Bytes, ein bisschen teuer in Code Golf. In vielen Situationen können Sie stattdessen überprüfen, ob das Array an einem bestimmten Punkt etwas enthält. Wenn Sie über den letzten Index nilhinausgreifen, erhalten Sie einen falschen Wert.

So können Sie Folgendes ändern:

if a.length<5bis if !a[4]für -5 Bytes

oder

if a.length>5bis if a[5]für -6 Bytes

oder

if a.length<nbis if !a[n-1]für -3 Bytes

oder

if a.length>nbis if a[n]für -6 Bytes

Hinweis : Funktioniert nur mit einem Array aller Wahrheitswerte. Das Vorhandensein niloder falsedas Einfügen in das Array kann zu Problemen führen.


4
Ich benutze immer size... Aber das ist definitiv besser. BTW, funktioniert Stringauch.
manatwork

10

Verwenden Sie nicht die Schlüsselwörter trueund false.

Verwenden:

  • !pfür true(danke, Histokrat!)
  • !0für false. Wenn Sie nur einen falschen Wert benötigen, können Sie einfach p(den Rückgabewert nil) verwenden.

um ein paar Zeichen zu sparen.


1
Sofern Sie nicht wirklich brauchen true(dh wenn ein wahrer Wert ausreicht, wie in einer if-Bedingung), brauchen Sie nicht einmal !!.
Martin Ender

4
Und in ähnlicher Weise ist p(was auswertet nil) ein kürzerer Falsey-Wert. Was bedeutet, der kürzeste Weg trueist !p.
Histokrat

@histocrat guter Punkt! Ich habe meine Antwort bearbeitet.
Cristian Lupascu


9

Wenn Sie jemals brauchen eine Reihe von bekommen ARGV, getoder etwas ähnlichem etwas , das oft zu tun, statt Aufrufto_i auf ihn können Sie nur verwenden , ?1.upto x{do something x times}wobei x eine Zeichenfolge ist.

Also mit ?1.upto(a){}x.to_i.times{}Wenn Sie anstelle von verwenden , sparen Sie 2 Zeichen.

Sie können auch Dinge wie p 1 while 1oder umschreibenp 1 if 1 als p 1while 1oder umschreibenp 1if 1

Dieses Beispiel ist nicht sehr nützlich, könnte aber für andere Zwecke verwendet werden.

Wenn Sie das erste Element eines Arrays einer Variablen zuweisen müssen, a,=cwerden im Gegensatz zu zwei Zeichen gespeicherta=c[0]


9

Neue Funktionen in Ruby 2.3 und 2.4

Es ist gut, sich über neue Sprachfunktionen zu informieren, die Ihrem Golfspiel helfen. In den neuesten Rubinen gibt es einige großartige.

Ruby 2.3

Der sichere Navigationsbetreiber: &.

Wenn Sie eine Methode aufrufen, die möglicherweise zurückgibt, nilaber wenn dies nicht der nilFall ist, möchten Sie zusätzliche Methodenaufrufe verketten, verschwenden Sie Bytes, die den Fall behandeln:

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

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

Der "Safe Navigation Operator" stoppt die Kette von Methodenaufrufen, wenn man zurückgibt nilund nilfür den gesamten Ausdruck zurückgibt :

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

Array#dig & Hash#dig

Tiefgreifender Zugriff auf verschachtelte Elemente mit einem schönen Kurznamen:

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

Gibt zurück, nilwenn es eine Sackgasse erreicht:

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

Enumerable#grep_v

Die Umkehrung von - Enumerable#grepgibt alle Elemente zurück, die nicht mit dem angegebenen Argument übereinstimmen (verglichen mit ===). Wie grep, wenn ein Block gegeben sein Ergebnis wird stattdessen zurückgegeben.

(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

Gibt einen Proc zurück, der den Wert für den angegebenen Schlüssel liefert, was sehr praktisch sein kann:

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]

Ruby 2.4

Ruby 2.4 ist noch nicht verfügbar, wird aber bald verfügbar sein und einige großartige kleine Funktionen bieten. (Wenn es veröffentlicht wird, aktualisiere ich diesen Beitrag mit einigen Links zu den Dokumenten.) Die meisten davon habe ich in diesem großartigen Blog-Beitrag erfahren .

Enumerable#sum

Nicht mehr arr.reduce(:+). Das kannst du jetzt einfach machen arr.sum. Es wird ein optionales Anfangswertargument verwendet, das für numerische Elemente ( [].sum == 0) den Standardwert 0 hat . Für andere Typen müssen Sie einen Anfangswert angeben. Es akzeptiert auch einen Block, der vor dem Hinzufügen auf jedes Element angewendet wird:

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

Integer#digits

Dies gibt ein Array der Ziffern einer Zahl in der Reihenfolge der niedrigsten bis höchsten Signifikanz zurück:

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

Im Vergleich zu sagen 123.to_s.chars.map(&:to_i).reverse, das ist ziemlich schön.

Als Bonus gibt es ein optionales Grundargument:

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

Comparable#clamp

Tut was es verspricht:

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

Da es in Comparable enthalten ist, können Sie es mit jeder Klasse verwenden, die Comparable enthält, zB:

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

String#unpack1

Einsparungen von 2 Byte gegenüber .unpack(...)[0]:

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

Präzisions - Argument für Numeric#ceil, floorundtruncate

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

Mehrfachzuordnung in Bedingungen

Dies löst einen Fehler in früheren Ruby-Versionen aus, ist jedoch in 2.4 zulässig.

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

Golf Math::E.ceil(1)zu Math::E.ceil 1und ebenfalls für floorund truncate.
Einfach schön Kunst

1
@SimplyBeautifulArt Ich gehe davon aus, dass jemand, der in Ruby Golf spielt, diesen Sprung selbst schaffen kann.
Jordan

Für Enumerable#sum, .flatten.sumist 2 Byte kürzer als.sum{|a,b|a+b}
asOne Tuhid

(-Math::E).truncate(1)entspricht -Math::E.truncate(1)dem ist 1 Byte kürzer
Asone Tuhid

1
&.kann mit einem solchen Index verwendet werden a&.[]i(1 Byte kürzer als a&.at i). Obwohl, wenn Klammern erforderlich sind, a||a[i]ist 1 Byte kürzer als a&.[](i)odera&.at(i)
Asone Tuhid

7

Wissenschaftliche Notation kann oft verwendet werden, um ein oder zwei Zeichen zu entfernen:

x=1000
#versus
x=1e3

9
Hinweis: Dadurch wird anstelle einer Ganzzahl ein Gleitkommawert (1000.0) zurückgegeben, der bei großen Zahlen zu ungenauen Ergebnissen führen kann.
Dogbert

4
Ah, schön 1e2ist besser, als 100.0wenn ein Prozentsatz benötigt wird.
Phrogz

Ähnlich wie bei diesem Prinzip 1.0*ist 1 .to_f
Zeichen

7

Verwenden Sie Operatormethoden anstelle von Klammern

Angenommen, Sie möchten ausdrücken a*(b+c). Funktioniert aus Gründen des Vorrangs a*b+c(offensichtlich) nicht. Rubys coole Art, Operatoren als Methoden zu haben, ist die Rettung! Sie können verwenden a.*b+c, um den Vorrang von *niedriger als den von zu machen +.

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

Dies kann auch mit den Operatoren !und funktionieren ~(Dinge wie unary +oder unary -funktionieren nicht, weil ihre Methoden so sind-@ und sind +@, speichern, ()aber hinzufügen .@)

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

6

Verwenden Sie ||stattdessen orund &&stattdessen and.

Neben dem einen Charakter aus and Sie die Leerzeichen (und möglicherweise die Klammer) um den Operator herum speichern.

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

Wenn Sie eine Schleife auf einem Array ausführen, verwenden Sie normalerweise each. Aber mapSchleifen auch über ein Array , und es ist ein Zeichen kürzer.


6

Ich habe gerade versucht, eine TDD-Code-Golf-Challenge durchzuführen, dh, ich schreibe den kürzesten Code, um die Spezifikationen zu erfüllen. Die Angaben waren so etwas wie

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

Für Code-Golf muss kein Modul oder keine Klasse erstellt werden.

Anstatt von

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

man kann tun

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

Speichert 13 Zeichen!


7
Ha, sehr gründlich. Nicht nur , dass fügen Sie das notwendige Verhalten PigLatin, sondern auch @pig_latin, $pig_latinund 'pig'['latin'].
Histokrat

@histocrat: Jetzt verstehe ich es. Es liegt daran translate, dass am definiert wurde nil.
Eric Duminil

6

Kernel # p ist eine unterhaltsame Methode.

Verwenden Sie p varanstelle vonputs var . Dies funktioniert perfekt mit ganzen Zahlen und Gleitkommazahlen, aber nicht mit allen Typen. Zeichenfolgen werden in Anführungszeichen gesetzt. Dies ist wahrscheinlich nicht das, was Sie möchten.

Wird mit einem einzigen Argument verwendet. p das Argument nach dem Drucken zurückgegeben.

Wird mit mehreren Argumenten verwendet. p die Argumente in einem Array zurückgegeben.

Verwenden Sie p(ohne Argumente) anstelle von nil.


10
Leider p 'some string'druckt "some string"nicht nur some stringwas oft von anderen kritisiert wird.
Patrick Oscity

1
Grundsätzlich p sist es dasselbe wie puts s.inspect, aber es kehrt zurücks
Cyoce

6

Verwenden Sie nicht #each. Mit #map können Sie alle Elemente in einer Schleife durchlaufen. Also statt

ARGV.each{|x|puts x}

Sie können dasselbe in weniger Bytes tun.

ARGV.map{|x|puts x}

Natürlich puts $*wäre in diesem Fall noch kürzer.


Es gibt Literale für rationale und komplexe Zahlen:

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

=> true
true
true

Sie können die meisten Bytes in Strings verwenden. "\x01"(6 Bytes) können auf ""(3 Bytes) gekürzt werden . Wenn Sie nur dieses eine Byte benötigen, kann dies noch weiter verkürzt werden? (2 Byte) .

Aus dem gleichen Grund können Sie Zeilenumbrüche wie folgt kürzen:

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

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

Sie können auch ?\nund verwenden ?\t, das ist ein Byte kürzer als "\n"und "\t". Zur Verschleierung gibt es auch ein Leerzeichen.


Verwenden Sie Konstanten, anstatt Argumente zu übergeben, auch wenn Sie sie ändern müssen. Der Dolmetscher wird stderr warnen , aber wen interessiert das? Wenn Sie weitere miteinander in Beziehung stehende Variablen definieren möchten, können Sie diese wie folgt verketten:

A=C+B=7+C=9

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

Dies ist kürzer als C=9;B=16;A=17oder C=0;B=C+7;A=C+B.


Wenn Sie eine Endlosschleife benötigen, verwenden Sie loop{...}. Schleifen unbekannter Länge können mit anderen Schleifen kürzer sein:

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

while'
'!=f(gets);end

Noch ein paar gsub / regexp-Tricks. Verwenden Sie die speziellen '\1'Escape-Zeichen anstelle eines Blocks:

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

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

Und die speziellen Variablen $1usw., wenn Sie Operationen ausführen müssen. Denken Sie daran, dass sie nicht nur innerhalb des Blocks definiert sind:

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

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

Entfernen Sie Leerzeichen, Zeilenumbrüche und Klammern. Bei Ruby kann man einiges weglassen. Wenn Sie Zweifel haben, versuchen Sie immer, wenn es ohne funktioniert, und denken Sie daran, dies könnte einige Editor-Syntax-Hervorhebungen beschädigen ...

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

"Bitte posten Sie einen Tipp pro Antwort." ?\nIst auch nett, aber nicht wirklich kürzer als das Setzen eines Zeilenumbruchs in Anführungszeichen. (Gleiches gilt für die Registerkarte)
Martin Ender

Und puts$*ist noch kürzer.
Cyoce

Ich weiß, dass Sie versucht haben, einen Punkt zu beweisen, aber ich bin mir ziemlich sicher, dass das letzte Beispiel dasselbe ist wiex+=1;$*<<A
Asone Tuhid

6

Noch eine andere Möglichkeit, den splat-Operator zu verwenden: Wenn Sie ein einzelnes Array-Literal zuweisen möchten, ist a *auf der linken Seite kürzer als eckige Klammern auf der rechten Seite:

a=[0]
*a=0

Bei mehreren Werten benötigen Sie nicht einmal den splat-Operator (danke an histocrat, der mich korrigiert hat):

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

Letzterer Fall benötigt den Splat eigentlich nicht.
Histokrat

@histocrat Oh wow, ich dachte, der zweite Wert würde in diesem Fall einfach verworfen.
Martin Ender

1
Ich kann nicht glauben, dass ich das in all der Zeit, die ich in Ruby verbracht habe, nicht gekannt habe.
Türklinke

6

Wenn eine Herausforderung erfordert , dass Sie die Ausgabe über mehrere Zeilen, Sie haben nicht zu Schleife durch Ihre Ergebnisse, um jede Zeile von zB einem Array zu drucken. Die putsMethode reduziert ein Array und druckt jedes Element in einer separaten Zeile.

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

Wenn Sie den splat-Operator mit #pIhnen kombinieren, können Sie ihn noch kürzer machen:

p *a

Der splat-Operator (technisch gesehen die *@Methode) wandelt auch Ihre Nicht-Array-Enumerables in Arrays um:

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

vs

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

1
*@ist keine Methode, Splat ist syntaktischer Zucker
Asone Tuhid

6

Speichern Sie einige Bytes, wenn Sie wiederholte Elemente eines Arrays entfernen

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

Wenn Sie ein leeres Array []in einer Variablen verwenden, können Sie noch mehr Bytes sparen:

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

2
Für den ersten Fall a&aist 1 Byte kürzer
Asone Tuhid

5

Verwenden Sie Goruby anstelle von Ruby, einer abgekürzten Version von Ruby. Sie können es mit rvm über installieren

rvm install goruby

In Goruby können Sie den größten Teil Ihres Codes so schreiben, wie Sie Ruby schreiben würden, es sind jedoch zusätzliche Abkürzungen integriert. Um die kürzeste verfügbare Abkürzung für etwas herauszufinden, können Sie shortest_abbreviationbeispielsweise die Hilfsmethode verwenden :

shortest_abbreviation :puts
#=> "pts"

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

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

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

Sehr praktisch ist auch der Alias, saymit putsdem sich selbst abkürzen lässt s. Also statt

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

Sie können jetzt schreiben

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

das Alphabet in Großbuchstaben zu drucken (was kein besonders gutes Beispiel ist). In diesem Blog-Beitrag werden weitere Themen und einige Aspekte des Innenlebens erläutert, wenn Sie weiterlesen möchten.

PS: hLass dir die Methode nicht entgehen ;-)


Mehr als zwei Jahre später habe ich endlich herausgefunden, woran mich diese Antwort erinnert ...
undergroundmonorail

5

Stattdessen einem Array beitreten

[...].join

mach das

[...]*''

Das spart 2 Bytes. Um sich mit einem Trennzeichen zu verbinden, verwenden Sie

[...]*?,

5

Subskriptionsnummern!

Ich habe das erst gestern entdeckt. n[i]Gibt ndas Bit an der i-ten Position zurück. Beispiel:

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

Und jetzt können Sie mehr Argumente wie verwendenn[0..3]
Einfach schöne Kunst

4

Möglicherweise können Sie 2 Zeichen speichern und verwenden

[*(...)]

Anstatt von

(...).to_a

Angenommen, wir möchten einen Bereich als Array definieren:

(1..2000).to_a

Mach es einfach so:

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

Und jetzt haben Sie Ihre Reichweite als Array.


5
Ich denke [*1..2000]funktioniert auch?
Lynn

4

<< Trick

a.push x

kann gekürzt werden auf:

a<<x

für -4 Bytes.


2
Hinweis: Dies funktioniert auch für Strings
Cyoce

4

Array#assoc/rassoc

Wenn Sie ein Array von Arrays haben und das Unterarray suchen möchten, das mit einem bestimmten Wert beginnt, verwenden Sie nicht Enumerable#find, sondern verwenden Sie Array#assoc:

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

Dies ist auch ein guter Ersatz für Enumerable#any? in manchen Situationen .

Array#rassoc tut dasselbe, prüft aber das letzte Element des Subarrays:

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

Was macht die a.any?Zeile im rassoc Beispiel |x,|? Wie unterscheidet es sich von |x|?
Cyoce

@Cyoce Bausteinparameter Destrukturierung folgt den gleichen Regeln wie Zuordnung Destrukturierung, so ist es wie x=[1,2]vs x,=[1,2]. Mit meinem obigen Beispiel wird mit |x|in der ersten Iteration xsein [0,"foo"]. Mit |x,y|, xwird 0und ywird sein "foo". Ebenso mit |x,|,x wird 0. Mit anderen Worten heißt es: "Setze das erste Element ein xund wirf den Rest weg.
Jordan

Beachten Sie, dass es nicht umgekehrt funktioniert, z. B. |,y|ein SyntaxError, ergo |_,y|. Aber ich habe gerade erst gemerkt, dass das |*,y|funktioniert, was sauberer ist als die Verwendung einer Variablen namens _(aber nicht kürzer).
Jordanien
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.