Ergebnis 1 bis 13 von 13

Thema: Problem beim Umgang mit Array

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Noch einfacher kann man sich das Leben mit select machen. Select filtert ein Array nach einer bedingung, in deinem Beispiel wäre das:
    @skills = @skills.select{|s| s >= 25}
    Sollte eigentlich einfach verständlich sein, im Grunde gibst du in den { } select eine Funktion mit, nach der gefiltert werden soll. Mit |s| gibst du an, in welche Variable die einzelnen Werte gespeichert werden sollen, damit du damit irgendwas machen kannst (könnte auch ein beliebiger anderer Bezeichner sein), danach gibst du die Bedingung an. Alle Elemente die die Bedingung erfüllen bleiben drin, der Rest fliegt raus.
    Ein Aufruf [1,26,5,30,2].select{|s| s >= 25} würde beispielsweise [26,30] zurückgeben. Dabei ist zu beachten, dass select ein neues Array zurückgibt und das Originalarray unverändert lässt. Ich hoffe, dass war jetzt etwas hilfreich und nicht mehr verwirrend ^^
    Es gibt eigentlich recht viele hilfreiche Methoden auf Array von Ruby, es lohnt sich, da mal die Dokumentation (http://www.ruby-doc.org/core-1.9.3/Array.html) durchzulese - Da findet man einige Methoden, die einem das leben oft einfacher machen

    Was ich noch etwas merkwürdig finde ist der Gesamteffekt deiner Methode. Du tust neue Werte in das Array, allerdings sind alle möglichen neuen Werte kleiner als 25, und werden dann wieder rausgefiltert? Oder sehe ich das falsch?

  2. #2
    Zitat Zitat
    leider ist das bei dem komischen Ruby kaum zu erkennen, dass es dort auch klassische Zeiger gibt...
    Es gibt in Ruby auch keine klassischen Zeiger. Im Prinzip musst du dir das so vorstellen, dass alle Objekte in Ruby nur über "Zeiger" referenziert werden. Call-by-Value gibt es in Ruby nicht (wobei es bei konstanten wie z.B. Integer-Literalen keine Rolle spielt ob sie referenziert oder kopiert werden). Das Zeiger setze ich mal in Anführungszeichen, weil die Ruby-Variablen eigentlich nicht wie richtige Zeiger funktionieren. Du kannst zwar Referenzen auf ein Objekt halten, aber z.B. nicht auf eine Variable (so irrsinnige Sachen wie Pointer auf einen Pointer auf eine Variable, wie in C Gang und Gäbe, gibt es in Ruby nicht).
    Wenn du von C kommst, dürfte das Konzept von Ruby erstmal gewöhnungsbedürftig sein. Aber ich denke es sollte klar sein, dass solche Konzepte wie Zeiger bei einer Scriptsprache einfach keinen Sinn machen, da sie viel zu fehleranfällig sind.

    Zum Problem: Es wurde ja eigentlich schon alles gesagt. Schleifen (sowohl while als auch for) würde ich in Ruby nicht verwenden. Es gibt stattdessen die Iteratoren, die das viel einfacher und besser können. Statt select kannst du auch delete_if nehmen. Das wirkt in-place (gibt also keine Kopie des Arrays zurück).
    Code:
    @skills.delete_if {|id| id < 25}
    Statt mehrfaches aufrufen von push kannst du auch << verwenden (also array << element1 << element2).

  3. #3
    Zitat Zitat von Fatalis Beitrag anzeigen
    Oder sehe ich das falsch?
    Ja, tust du und Cornix in der Hinsicht wohl Das @skills-Array ist eigentlich immer sortiert, bevor meine Funktion aufgerufen wird. Deshalb sind die kleinen Werte am Anfang. Wenn ich dann neue pushe, kommen die ans Ende. Dadurch werden auch doppelte aussortiert, weil im Grunde ja nur die kleinen am Anfang verschwinden, am Ende aber bleiben.
    Zugegeben, das ist alles andere als schön, aber solange es funktioniert.

    Allerdings werde ich trotzdem mal .select oder .delete_if ausprobieren.

    Dank auch an KD, das bringt mein Verständnis von Ruby nochmal ein Stückchen weiter. Scheint so, als wäre das wohl alles mehr Umgewöherei als ich vermutet habe. Aber solange man Hilfe bekommt ist ja alles in Ordnung.

    Danke euch allen.

  4. #4
    Zitat Zitat von Rettan Beitrag anzeigen
    Ja, tust du und Cornix in der Hinsicht wohl Das @skills-Array ist eigentlich immer sortiert, bevor meine Funktion aufgerufen wird. Deshalb sind die kleinen Werte am Anfang. Wenn ich dann neue pushe, kommen die ans Ende. Dadurch werden auch doppelte aussortiert, weil im Grunde ja nur die kleinen am Anfang verschwinden, am Ende aber bleiben.
    Zugegeben, das ist alles andere als schön, aber solange es funktioniert.
    Ah okay, dachte mir dass da etwas mehr dahintersteckt
    In dem Fall kommst du mit select oder delete_if auch nicht viel weiter, da diese Methoden dann auch deine neuen Werte, die du gerade gepusht hast, rausfiltern würden. Dann müsstest du select / delete_if aufrufen, bevor du die neuen Werte reinpusht.

    Würde also folgenden Code geben:

    Code:
     def angriffe_setzen(waffe)
       @skills.delete_if{|s| s<25}
    
        if waffe.include?("!M")  
          @skills << 3
     ....
    Potentielles Problem mit deinem Codeschnipsel mit while seh ich dann noch, wenn kein Skill mit einer Nummer größer als 25 drin ist würde er die neuen Werte trotzdem löschen. Also bei [1,25,1] würde [25,1] rauskommen, bei [1,24,2] aber ein leeres Array.

    Und mal nebenbei, um sicher zu gehen, dass ich deine Absicht jetzt richtig verstanden habe:
    Skills >= 25 sind permanente Skills, Skills < 25 sind waffenabhängig und wenn man die Waffe wechselt, vergisst man alle Skills (<25) der alten Waffe und kann nur noch die Skills der neuen Waffe.
    Wird aus deiner Eingangsfrage wirklich nicht ganz klar, deshalb denke ich haben auch viele den Nutzen der Schleife am Ende missverstanden

    Geändert von Fatalis (12.12.2011 um 17:41 Uhr) Grund: Codeschnipsel

  5. #5
    Zitat Zitat von Fatalis Beitrag anzeigen
    Potentielles Problem mit deinem Codeschnipsel mit while seh ich dann noch, wenn kein Skill mit einer Nummer größer als 25 drin ist würde er die neuen Werte trotzdem löschen. Also bei [1,25,1] würde [25,1] rauskommen, bei [1,24,2] aber ein leeres Array.
    Stimmt eigentlich, aber das Problem war sogar schon unbewusst dadurch gelöst, dass es einen Standard-Skill gibt den jeder Charakter von Anfang an hatte.

    Zitat Zitat von Fatalis Beitrag anzeigen
    Und mal nebenbei, um sicher zu gehen, dass ich deine Absicht jetzt richtig verstanden habe:
    Skills >= 25 sind permanente Skills, Skills < 25 sind waffenabhängig und wenn man die Waffe wechselt, vergisst man alle Skills (<25) der alten Waffe und kann nur noch die Skills der neuen Waffe.
    Wird aus deiner Eingangsfrage wirklich nicht ganz klar, deshalb denke ich haben auch viele den Nutzen der Schleife am Ende missverstanden
    Bingo
    Ich war beim erklären von Problemen noch nie sehr gut, weil mir beim erklären meist potenzielle Lösungen in den Kopf komen, die ich dann entweder direkt ausprobieren oder drüber nachdenken muss. Daher komm ich beim erklären oft durcheinander oder bekomme verkorkste Erklärungen hin.
    Aber auf lang oder kurz wusstet ihr ja worum es geht.

    Und da ich jetzt auch endlich mal Zeit habe, werde ich es jetzt auch mal umsetzen...

  6. #6
    Ich finde dein Konstrukt weder sinnhaft noch sonderlich einfach gestaltet.
    Warum speicherst du permanente Skills und Waffenskills nicht in zwei verschiedenen Arrays? Dann musst du dich weniger damit rumplagen wo was steht und welche ID ein Skill hat.

  7. #7
    @Rettan @Cornix
    Zitat Zitat
    Dann ist das Break keinesfalls richtig.

    Hier ein Beispiel mit deinem Code:
    @skills[0] = 4
    @skills[1] = 27
    @skills[2] = 9

    Was würde nach der Ausführung von diesem Code-Abschnitt passieren:

    Code:
    i = 0     
    while i < @skills.size
          if @skills[i] < 25
            @skills.delete_at(i)
            i -= 1
          else
            break
          end
          i += 1
        end
    Ganz einfach:

    Schritt 1:
    i = 0
    @skills[0] == 4 < 25 => true
    -> @skills.delete_at(0)

    Schritt 2:
    i = 1
    @skills[1] == 27 < 25 => false
    -> break
    Die Schleife so zu benutzen ist eh semantisch falsch, wenn man keinen iterator benutzt.
    Schritt 1 löscht @skills[0]
    Ruby unshiftet das Array jetzt - was vorher @skills[1] war, rutscht an die freigewordene Stelle von @skills[0]
    Schritt 2 würde jetzt also mit @skills[1]=9 arbeiten - das ursprüngliche @skills[1]=27 würde ignoriert werden. In dem Fall der gewünschte Effekt, aber vertausche 9 und 27 in dem Beispiel, und du hast einen unerwünschten Effekt. Schritte dagegen sind i in dem Fall einer Löschung runterzusetzen oder gleich iteratoren zu nehmen

    @KD
    Du magst recht haben, aber je nachdem wie eingearbeitet man ist und woher man kommt, ist man halt gewohnt mit while und for zu arbeiten - seit dem ich sie kenne nutze ich gerne Iteratoren, aber nehm auch gern hier und da eine for - aus gewohnheit, weil ich es dann besser lesen kann und weil ich auch nicht alle iteratoren kenne. Gerader der lesbarkeithalber bevorzuge ich for-Schleifen sogar vor Array#each und Numeric#times - solange es hinterher funktioniert^^.
    Zumindest solange es bei RGSS bleibt, wenn man vernünftige Programme mit Ruby schreiben will ist es durchaus korrekt, sich das erst garnicht anzugewöhnen. Aber ein Großteil der User hier gehört wohl eher zu den Leuten, die damit nicht ausserhalb des RGSS arbeiten wollen.

    @include?("")-Thema
    Hm, okay, ich hatte es vermutet dass String die Funktion hat, ich konnte es mir nur nicht bestätigen. Wenn es also wirklich um String#include? geht, dann,Rettan, ergibt weder .include?("") noch !.include?("") Sinn - wenn das Element wirklich ein String ist, ist der leere String immer enthalten - da würde sich eher ein Codezeichen für Anbieten, sei es irgendein sonst unbenutztes Zeichen inkl. dem Leerzeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •