2016-04-20 12 views
0

Das Ziel ist es, zu finden, ob der Buchstabe 'a' innerhalb einer Zeichenfolge ist und die drei Positionen weg von den 'a' Vorkommen innerhalb der Zeichenfolge hinzufügen.finden Sie Buchstaben innerhalb der Zeichenfolge und erhalten Positionen - Ruby

Also wenn die Zeichenfolge 'gabe' wäre, würde meine Liste wie diese Liste aussehen = [2,3,4]. Wenn die Zeichenfolge 'Gabba' dann list = [2,3,4,5,6,7]

mein aktueller Code scheint mir Fehler

def nearby_az(string) 
list = [] 
for i in 0..(string.length) 
    if string[i] == 'a' 
     list.push(i+1) 
     list.push(i+2) 
     list.push(i+3) 
     next 
    end 
return list 

Ende

mir zu geben Erhalte den folgenden Fehler: (repl): 11: Syntaxfehler, unerwartetes Ende der Eingabe, erwartet keyword_end

Kannst du sehen, wo meine Logik abfällt?

+1

Sie benötigen noch ein '' 'Ende''', um die Funktionsdefinition zu schließen. –

+1

"Kannst du sehen, wo meine Logik abfällt?" - Ruby sagt dir, dass es ein * Syntax * -Fehler ist. Da der Code nicht einmal geparst werden kann, kann er offensichtlich auch nicht ausgeführt werden, und somit kann dies unmöglich etwas mit Ihrer Logik zu tun haben, da Ihre Logik niemals ausgeführt wird. –

+1

Ich habe gestern eine Stunde verbracht, aber nicht verstanden, was ich falsch mache. Gut, dass ich eher früher als später gefragt habe. Das war alles was ich brauchte - und extra 'Ende'! – hac13

Antwort

1

Der Fehler rührt daher, dass Sie den Bereichsblock nicht mit einem Ende geschlossen haben. Aber es gibt noch andere Punkte. Ich schlage vor, Sie so etwas zu versuchen:

def nearby_az(str) 
    list = Array.new 
    pos = -1 
    str.each_char do |c| 
    pos = pos + 1 
    if (c == 'a') then 
     list.push(pos+1) 
     list.push(pos+2) 
     list.push(pos+3) 
    end 
    end 
    list 
end 

oder noch besser

def nearby_az(str) 
    list = Array.new 
    nstr = str.each_char.to_a 
    nstr.each_index do |i| 
    if (nstr[i] == 'a') then 
     list.push(i+1) 
     list.push(i+2) 
     list.push(i+3) 
    end 
    end 
    list 
end 

(Diese Möglichkeiten, die Sie nicht einmal einen künstlichen Index erstellen haben, indem sie den natürlichen Index des nstr mit Array)

Mit diesem Code, wenn Sie das tun

puts nearby_az("asdfgaqwer") 

wird das Ergebnis wie gewünscht [1, 2, 3, 6, 7, 8] sein.

Denken Sie daran, Sie brauchen keine Rückkehr in Ruby. Der Wert des letzten in einer Methode berechneten Ausdrucks wird standardmäßig an den Methodenaufrufer zurückgegeben.

Natürlich können Sie auch weiterhin Ihren Weg verwenden, dies zu tun:

def nearby_az(string) 
    list = [] 
    for i in 0..(string.length) 
    if string[i] == 'a' 
     list.push(i+1) 
     list.push(i+2) 
     list.push(i+3) 
    end 
    end 
    list 
end 

Und es wird Ihnen das gleiche Ergebnis, obwohl ich der erste Code denken ein bisschen leichter zu lesen ist.

1

Hier ist eine Ruby-ähnliche Weise, die Sie tun könnten.

-Code

def indices(str) 
    str.each_char. 
     with_index. 
     select { |c,_| c=='a' }. 
     flat_map { |_,i| (i..i+2).to_a } 
end 

Beispiele

indices "gabe" 
    #=> [1, 2, 3] 
indices "gabba" 
    #=> [1, 2, 3, 4, 5, 6] 
indices "abbadabbadoo" 
    #=> [0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10] 

Erklärung

Angenommen

str = "gagga" 

Dann sind die Schritte wie folgt:

enum0 = str.each_char 
    #=> #<Enumerator: "gagga":each_char> 
enum1 = enum0.with_index 
    #=> #<Enumerator: #<Enumerator: "gagga":each_char>:with_index> 

vorsichtig den oben Rückgabewert prüfen. Sie können sich enum1 als Compound Enumerator vorstellen (obwohl Ruby kein solches Konzept hat - enum1 ist einfach ein Enumerator). Wir können die Elemente von enum1 sehen, die von enum1 auf ein Array Umwandlung zu select weitergegeben wird:

enum1.to_a 
    #=> [["g", 0], ["a", 1], ["g", 2], ["g", 3], ["a", 4]] 

Continuing,

a = enum1.select { |c,_| c=='a' } 
    #=> [["a", 1], ["a", 4]] 
a.flat_map { |e,i| (i..i+2).to_a } 
    #=> [1, 2, 3, 4, 5, 6] 

Enumerable#flat_map ‚s Blockvariablen sind e und i.

e, i = ["a", 1] 
    #=> ["a", 1] 
e #=> "a" 
i #=> 1 

und den Block Berechnung wird durchgeführt:: wenn das erste Element des a (["a", 1]) an den Block übergeben wird, werden die Blockvariablen parallel Zuordnung Verwendung zugewiesen

(i..i+2).to_a 
    #=> (1..3).to_a 
    #=> [1,2,3] 

anzumerken, dass flat_map entspricht:

b = a.map { |e,i| (i..i+2).to_a } 
    #=> [[1, 2, 3], [4, 5, 6]] 
c = b.flatten(1) 
    #=> [1, 2, 3, 4, 5, 6] 

Eine letzte Sache: flat_map 's erste Blockvariable, e, wird nicht in der Blockberechnung verwendet. Wie in solchen Situationen üblich, wird stattdessen _ (eine zulässige lokale Variable) für diese Variable verwendet. Dies informiert den Leser, dass diese Blockvariable nicht verwendet wird, und kann auch die Wahrscheinlichkeit verringern, Fehler innerhalb des Blocks einzuführen.

+0

Ausgezeichnete Antwort! Ich schlage vor, das OP akzeptiert Ihre Antwort statt meiner! Vielen Dank für die Gelegenheit, mehr Ruby zu lernen. –

+1

Danke, @EddeAlmeida, aber vergessen Sie nicht, das OP ist aufgefordert, die Antwort auszuwählen, die für ihn oder sie am hilfreichsten war.Sie haben das Problem mit dem OP-Code erklärt, was ich nicht getan habe, und manchmal werden Verbesserungen an einem vertrauten Ansatz mehr geschätzt als eine ganz andere Art, das Problem anzugehen. Meine Antwort war genauso für andere Leser als für das OP. –

+0

Am Ende hat das OP keine Antwort gewählt ... LOL –

Verwandte Themen