Table wird nicht gefüllt?

  • Hallo zusammen.
    Ich muss mal wieder meine beschränkten Programmierkünste zur Schau stellen ;)
    Kann mir einer Sagen, warum bei nachfolgendem Code von table.getn die Null zurück geliefert wird?
    [lua] self.mySprays = {};
    self.mySprays[Fillable.FILLTYPE_UNKNOWN] = true;
    local sprayTypes = getXMLString(xmlFile, "vehicle.sprayFillTypes#fillTypes");
    if sprayTypes ~= nil then
    local types = Utils.splitString(" ", sprayTypes);
    for _,v in pairs(types) do
    print(v);
    local sprayType = Fillable.fillTypeNameToInt[v];
    print(sprayType);
    if sprayType ~= nil then
    self.mySprays[sprayType] = true;
    print(tostring(self.mySprays[sprayType]));
    else
    print("Warning: '"..self.configFileName.. "' has invalid sprayType '"..v.."'.");
    end;
    end;
    end;
    print(table.getn(self.mySprays));[/lua]

    prints in der Log:

    Code
    fertilizer
    23.000000
    true
    fertilizer2
    37.000000
    true
    fertilizer3
    38.000000
    true
    0.000000


    Gruß & Dank im voraus!

  • Hm... komisch ist das für mich auch.
    Aber ich habe deinen Code grad schnell mal in einen einfachen Trailer eingebaut und die fillTypes damit ausgelesen, also ("vehicle.fillTypes#fruitTypes");


    Die Fruchtsorten in der XML sind folgende:

    XML
    <fillTypes fruitTypes="wheat rape maize barley chaff potato sugarBeet manure"/>


    Die Ausgabe in der LOG sah so aus:


    Dazu war die Ausgabe von table.getn(self.mySprays) = 6.000000
    Was aus sehr komisch ist, da ich ja 8 FruitTypes eingetragen habe.


    Wenn ich dann aber mit:
    [lua] for k,v in pairs(self.mySprays) do
    print(k)
    print(v)
    end;[/lua]
    nochmal ein paar Ausgaben in die LOG schreiben lassen, dann kommt was ganz komisches dabei heraus:


    Also ist der Table ja eigentlich auch 8, bis zur 6 passt ja die durchnummerierung auch, aber dann ist es 9 und 24.
    Sprich du fügst ja die jeweilige "Fruchtnummer" in den Table ein. Ich weiß aber nicht ob leere Stellen nicht zu einer "Störung" von table.getn führen.


    Es kommt mir zumindest in diesem Test jetzt so vor, das sobald eine Stelle leer ist, table.getn=0 zurück gibt, Was dann auch dein Ergebnis erklären würde.



    Zur Not musst du vorher einfach eine Schleife einbauen, so wie es in den Standartskripten z.B beim Sprayer ab Zeile 66 gemacht wird:
    [lua] self.sprayLitersPerSecond = {};
    local i=0;
    while true do
    local key = string.format("vehicle.sprayUsages.sprayUsage(%d)", i);
    if not hasXMLProperty(xmlFile, key) then
    break;
    end;
    local fillType = getXMLString(xmlFile, key.. "#fillType");
    local litersPerSecond = getXMLFloat(xmlFile, key.. "#litersPerSecond");
    if fillType ~= nil and litersPerSecond ~= nil then
    local fillTypeInt = Fillable.fillTypeNameToInt[fillType];
    if fillTypeInt ~= nil then
    self.sprayLitersPerSecond[fillTypeInt] = litersPerSecond;
    if self.defaultSprayLitersPerSecond == nil then
    self.defaultSprayLitersPerSecond = litersPerSecond;
    end;
    else
    print("Warning: Invalid spray usage fill type '"..fillType.."' in '" .. self.configFileName.. "'");
    end;
    end;
    i = i+1;
    end;
    [/lua]
    Aber ob dir das hilft weiß ich nicht, kommt ja auch darauf an, was du genau damit vor hast. Aber hoffe ich konnte dir wenigstens etwas helfen.

  • Hmmm... Also angeblich ist table.getn() veraltet und wurde in LUA 5.1 (welches auch für LS13 verwendet wird) durch # ersetzt. Also #myTable anstatt table.getn(myTable). Der funktioniert aber nur bei Tabellen mit numerischen Indizes und gibt hier auch nur den höchsten Wert zurück.


    Bleiben also zwei saubere Möglichkeiten:
    1. Beim erstellen der Tabelle mitzählen, in eine Variable speichern, jede add- und delete-Operation tracken und die Zählervariable updaten.
    2. Mit pairs() über die Tabelle iterieren und zählen.

  • So, vielen Dank für die Hinweise.
    Da ich ohnehin nur gültige Werte eintrage, kann ich mir das "true" sparen, und nutze gleich den Index (k) aus types und habe dann fortlaufende Indexe mit dem jeweiligen Filltypewert:
    [lua] self.mySprays = {};
    local sprayTypes = getXMLString(xmlFile, "vehicle.sprayFillTypes#fillTypes");
    if sprayTypes ~= nil then
    local types = Utils.splitString(" ", sprayTypes);
    for k,v in pairs(types) do
    local sprayType = Fillable.fillTypeNameToInt[v];
    if sprayType ~= nil then
    self.mySprays[k] = sprayType;
    else
    print("Warning: '"..self.configFileName.. "' has invalid sprayType '"..v.."'.");
    end;
    end;
    end;[/lua]


    Ergebnis ist folgender table:
    [1][23]
    [2][37]
    [3][38]
    Damit funktioniert table.getn und # wieder wie es soll.


    Das ganze dient übrigens zum Durchschalten der verschiedenen Düngerarten im SoilMod.
    Die Funktion zum Durchschalten sieht dann so aus:
    [lua]function UrfSeeder:setCurrentSprayType(currentSprayFillType, noEventSend)


    local action = -1;


    for i,sprayType in ipairs(self.mySprays) do
    if sprayType ~= nil and sprayType == currentSprayFillType then
    for k=0,table.getn(self.mySprays) do
    i = (i % table.getn(self.mySprays))+1
    if self.mySprays[i] then
    action = self.mySprays[i];
    break;
    end;
    end;
    break;
    end;
    end;
    if action >= 0 then
    self.currentSprayFillType = action;
    end;
    end;[/lua]

  • Ich verstehe bei deinem Durschalten nur nicht so ganz was da passiert...


    [lua] for i,sprayType in ipairs(self.mySprays) do
    if sprayType ~= nil and sprayType == currentSprayFillType then
    for k=0,table.getn(self.mySprays) do
    i = (i % table.getn(self.mySprays))+1
    if self.mySprays[i] then
    action = self.mySprays[i];
    break;
    end;
    end;
    break;
    end;
    end;
    [/lua]
    Den Start also in pairs() verstehe ich ja noch, die abfrage mit sprayType ~= nil auch, soweit klar.


    Warum du dann aber mit k=0, die schleife anlegst, verstehe ich nicht, da die Tabelle doch eh mit 1 beginnt (aber gut du greifst ja eh nicht direkt drauf zu, also nicht mit self.mySprays[k] ). Denn im Grunde würde deine Schleife jetzt ja immer einmal mehr durchlaufen wie dein Table groß ist.


    Aber das mit dem modulo (%) verstehe ich jetzt mal ganz und gar nicht.


    i, ist ja der Platz in deinem Table. Und hat den (jetzt) den Wert des Durchlaufes, z.B 1. Dann veränderst du doch aber den Wert von i, oder sehe ich das jetzt falsch?


    i = (i / 3) +1,


    Wenn es im ersten Durchlauf der in pairs Schleife passiert das du die for schleife anfängst, dann heißt das doch:
    i = (1/3) +1 --1/3 ergibt durch modulo ja den Rest, also 1, da 1 nicht durch 3 teilbar ist, dann addierst du 1 dazu, somit ist i = 2.



    Das verstehe ich einfach nicht, oder habe grad nur ein Brett vor dem Kopf, was du damit erreichst?!
    Kannst du mir das mal erklären?

  • Warum du dann aber mit k=0, die schleife anlegst, verstehe ich nicht, da die Tabelle doch eh mit 1 beginnt


    Diese Schleife ist in der Tat nicht nötig.


    Wenn es im ersten Durchlauf der in pairs Schleife passiert das du die for schleife anfängst, dann heißt das doch:
    i = (1/3) +1 --1/3 ergibt durch modulo ja den Rest, also 1, da 1 nicht durch 3 teilbar ist, dann addierst du 1 dazu, somit ist i = 2.


    Das verstehe ich einfach nicht, oder habe grad nur ein Brett vor dem Kopf, was du damit erreichst?!
    Kannst du mir das mal erklären?


    Als ich bin zu dem Ergebnis gekommen, dass das Interessante hier erst passiert, wenn das Ende des tables erreicht ist: in meinem Fall drei. 3/3 = 1 Rest 0. Dann wird i durch +1 wieder auf den Anfang des tables gesetzt!
    Ginge natürlich auch anders.

  • Vielen Dank das du da nochmal genau nachgesehen hast. :thumbup:


    Mir kam es nur irgendwie komisch vor, aber ich lag ja zumindest richtig was die k=0 schleife angeht. ^^


    Ich bin mir jetzt nur nicht ganz sicher was die Abfrage: if self.mySprays[i] then angeht, ob die ein true zurück gibt wenn dein self.mySprays ein table ist?!
    Aber das brauchst du nicht testen, das kann ich beim nächsten mal wenn ich an einem Skript bin auch selber mal testen.


    Das man es auch anders lösen kann wie mit dem modulo ist richtig. Ich glaube mir wäre das auch als letztes eingefallen... ^^


    Falls du es bei dir anders lösen willst: http://planet-ls.de/board/inde…&postID=236723#post236723

  • So, nochmal n bisschen Senf. Hatte den Thread verpasst, da GC am Mittwoch.


    1. Bzgl. getn: #tableName ist identisch zu zu table.getn(tableName) (shorthand), sollte aber tunlichst benutzt werden da v5.2.
    # gibt den höchsten numerischen key n zurück, für den tableName[1 bis n] ~= nil ist. Sprich: 1 - 6 und 24 existieren als key, dann geht 24 nicht da 23 nicht existiert. Daher getn = 6. Wenn kein passender key gefunden wird, wird 0 zurückgegeben.


    2. Bzgl. iteration bei nicht-sequentiellen keys: next() ist immer für sowas gut. Nimmt auch nen Startindex als Argument, kann man also prima zum Durchschalten benutzen.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!