Liste mit Strings in String-Array casten

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen

 

Tritium

Betreff: Liste mit Strings in String-Array casten

BeitragSa, Nov 19, 2011 17:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Tag zusammen,

ich möchte eine TList, die nur Strings enthält, in ein Array von Strings überführen. Leider klappt das nicht so recht. Mein bisheriger Ansatz sieht so aus:

BlitzMax:
Framework BRL.Blitz
Import BRL.LinkedList

Strict

Local array$[] = Null
Local list:TList = CreateList()

ListAddLast(list,"Hans")
ListAddLast(list,"Dieter")
ListAddLast(list,"Horst")

array = String[](ListToArray(list))

For Local temp$ = EachIn array
WriteStdout(temp + "~n")
Next


Mein Array ist jetzt jedoch leer. Ich vermute, dass da was auf dem Weg vom TObject zum String nicht klappt. Weiß jemand, was ich falsch mache bzw. wie ich diese Umwandlung anders (und halbwegs effizient) hinbekomme?

Schonmal Danke für's Lesen! Very Happy

Xeres

Moderator

BeitragSa, Nov 19, 2011 17:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Du musst jedes Element einzeln Casten:
BlitzMax:
SuperStrict

Local list:TList = CreateList()

ListAddLast(list,"Hans")
ListAddLast(list,"Dieter")
ListAddLast(list,"Horst")

Local objarray:Object[] = ListToArray(list)
Local array:String[]
For Local i:Int = 0 Until objarray.Length
array:+[objarray[i].ToString()]
Next


Print("-> " + array.Length)
For Local temp:String = EachIn array
Print(temp)
Next


Edit: Eine Funktion, die die Liste annimmt und ein String[] liefert, wäre wahrscheinlich am besten...
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
 

Tritium

BeitragSa, Nov 19, 2011 17:31
Antworten mit Zitat
Benutzer-Profile anzeigen
Also bedeutet das, dass man eigentlich überhaupt nicht mit String[]() casten kann, es aber auch nicht als Fehler gemeldet wird?

Xeres

Moderator

BeitragSa, Nov 19, 2011 17:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Der Versuch Code:
String[](ListToArray(list))
zu casten wird einfach fehl schlagen und NULL liefern, das ist schon korrekt.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
 

Tritium

BeitragSa, Nov 19, 2011 18:01
Antworten mit Zitat
Benutzer-Profile anzeigen
Mh, das ist schade, wär schön einfach gewesen... Naja, kann man nix machen. Danke für die Antworten!
 

PhillipK

BeitragSa, Nov 19, 2011 18:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Das verstehe ich allerdings nicht.

Ich nutze das auch meist so :O

Sprich - MeinType[](Tlist.toArray) - und das funktioniert. :O

ZEVS

BeitragSa, Nov 19, 2011 18:42
Antworten mit Zitat
Benutzer-Profile anzeigen
BlitzMax Version 1.43/Windows:
BlitzMax:
Global list:TList = New TList
list.addLast "Hello"
list.addLast "World"
list.addLast "!"
Local strings$[] = String[](list.toArray())
Print list.Count()+"/"+strings.length
For Local str$ = EachIn strings
Print str
Next

Output: Code:
Building untitled2
Compiling:untitled2.bmx
flat assembler  version 1.69.14  (553925 kilobytes memory)
3 passes, 4129 bytes.
Linking:untitled2.debug.exe
Executing:untitled2.debug.exe
3/0

Process complete


ZEVS
 

Tritium

BeitragSa, Nov 19, 2011 20:02
Antworten mit Zitat
Benutzer-Profile anzeigen
@PhillipK: Eben, deswegen wundert es mich, dass es mit Strings jetzt nicht funktioniert.

@ZEVS: Ja, bei mir gehts auch nicht. Oder was genau meinst Du?

Xeres

Moderator

BeitragSa, Nov 19, 2011 20:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Mh.
Types funktionieren...
BlitzMax:
SuperStrict

Type TTest
Field n:Int

Method New()
Self.n = Rand(1, 5)
End Method
End Type

Global list:TList = New TList
list.addLast(New TTest)
list.addLast(New TTest)
list.addLast(New TTest)
Local objs:TTest[] = TTest[] (list.toArray())
Print list.Count() + "/" + objs.length
For Local o:TTest = EachIn objs
Print o.n
Next


Hin und her casten geht...
BlitzMax:
SuperStrict
Local txt:String[] = ["A", "B", "C"]
Print(", ".Join(txt))
Local obj:Object[] = Object[] (txt)
Print(obj.Length)
Local txt2:String[] = String[] (obj)
Print(", ".Join(txt2))


Nur von einer Liste nicht...
BlitzMax:
SuperStrict

Local list:TList = CreateList()

ListAddLast(list, "A")
ListAddLast(list, "B")
ListAddLast(list, "C")

Local obj:Object[] = list.ToArray()
Print(obj.Length)
Local txt:String[] = String[] (obj)
Print(txt.Length)
Print(", ".Join(txt))

Mh...

Edit: Siehe hier (verständlicher wird mir das Verhalten dadurch auch nicht, aber scheint kein Bug zu sein)
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
 

Tritium

BeitragSa, Nov 19, 2011 20:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Dein Link funktioniert leider nicht Sad

Xeres

Moderator

BeitragSa, Nov 19, 2011 20:49
Antworten mit Zitat
Benutzer-Profile anzeigen
Ist unter "Hidden Forums" - vermutlich musst du auf bb.com eingeloggt sein.
marksibly hat Folgendes geschrieben:
The issue here is that just because all the elements of the objs array are strings, they don't necessarily have to be - as far as the compiler's concerned, it's an Object[] which could contain *anything*.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
 

Tritium

BeitragSa, Nov 19, 2011 21:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Mh, das versteh ich nicht ganz. Ich war davon ausgegangen, dass beim Casten grundsätzlich erstmal versucht wird, aus einem TObject den spezifizierten Type zu machen. Sollte das nicht klappen, kommt Null als Ergebnis raus. Bei einem Array hab ich vermutet, dass das Element für Element passiert, also doch auch klappen müsste!?

Farbfinsternis

BeitragSa, Nov 19, 2011 21:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Es ist Banane ob das Array vom Typ String oder vom Typ Object ist:
BlitzMax:

SuperStrict

Local stringList:TList = New TList

stringList.AddLast("Hallo")
stringList.AddLast("schöne")
stringList.AddLast("neue")
stringList.AddLast("Welt!")

Local stringArray:Object[] = stringList.ToArray()

For Local tmp:String = EachIn stringArray
DebugLog tmp
Next
Farbfinsternis.tv

ZEVS

BeitragSa, Nov 19, 2011 21:52
Antworten mit Zitat
Benutzer-Profile anzeigen
So ganz "Banane" ist das nicht. Die For-EachIn list - Schleife castet nämlich automatisch.
Der bug wird durch Reflection offenbart:
BlitzMax:
Local obj:Object[] = ["A", "B", "C"]
Print TTypeId.ForObject(obj).Name()

Output:
Code:

String[]


Das mit Xeres' Beispiel:BlitzMax:
SuperStrict
Local txt:String[] = ["A", "B", "C"]
Print(", ".Join(txt))
Local obj:Object[] = Object[] (txt)
Print(obj.Length)
Local txt2:String[] = String[] (obj)
Print(", ".Join(txt2))
Print TTypeId.ForObject(obj).Name()

Output:
Code:

A, B, C
3
A, B, C
String[]

Es scheint eine BMax-Funktion zu geben, die Array-Types spezialisiert. Das ganze geht aber auch noch eindrucksvoller:
BlitzMax:
SuperStrict
Local txt:String[] = ["A", "B", "C"]
Print(", ".Join(txt))
Local obj:Object[] = Object[] (txt)
Print(obj.Length)
Local txt2:String[] = String[] (obj)
Print(", ".Join(txt2))
Print TTypeId.ForObject(obj).Name()
obj[1] = CreateTimer(20)
Print TTypeId.ForObject(obj).Name()
Print TTypeId.ForObject(obj[1]).Name()

Code:

A, B, C
3
A, B, C
String[]
String[]
TTimer

Schon toll, einen Timer im String-Array zu haben...

ZEVS
 

Tritium

BeitragSa, Nov 19, 2011 22:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Also bedeutet das, dass alle Arrays grundsätzlich vom Type TObject sind, ganz egal, wie sie eigentlich initialisiert wurden?

Edit: Mh, allerdings scheints mir nach Deinem Post auch so zu sein, dass das Casten intern keinen großen Effekt hat, schließlich scheint das String-Array nach dem Casten zu einem Object-Array immer noch ein String-Array zu sein... Ich hab grad Schwierigkeiten, das geistig vollständig zu durchdringen...

ZEVS

BeitragSa, Nov 19, 2011 22:51
Antworten mit Zitat
Benutzer-Profile anzeigen
1. Der Type heißt (entgegen der Konvention) nur Object. Falls du mal damit arbeitest, wirst du schon noch an daran verzweifeln (zumindest ich tue das).
2. Alles (ok, es gibt Ausnahmen, aber String ist keine) ist vom Type Object. Das liegt daran, dass jeder Type Object quasi "automatisch" erweitert.
3. Das Beispiel zeigt einen anderen Umstand: Es wurde ein Array als Object[] intalisiert, wurde aber durch die Wertverteilung zu String[], was an sich inkompatibel ist (jeder String ist Object, aber nicht jedes Object ist String). Das kratzt BMax aber nicht mal, wenn man wirklich mal einen nicht-String in das Array tut. So hat man am Ende einen TTimer im String[], obwohl das inkompatibel ist.

Wenn man aber eine Liste von Strings in ein Array umformt, dann ist das Ergebnis wirklich ein Object[], von Reflection bestätigt. Das gleiche gilt, wenn man die Werte nicht mit der Deklaration vorgibt. Xeres wollte sich bei seinem Beispiel Zeit sparen und hat die Werte kurz eingegeben - und dadurch unabsichtlich zu String[] gecastet. Deswegen funktioniert Xeres' Beispiel.

ZEVS
 

Tritium

BeitragSa, Nov 19, 2011 23:03
Antworten mit Zitat
Benutzer-Profile anzeigen
1. Da hast Du allerdings Recht.
2. Das ist mir schon klar.
3. Ich war bisher immer davon ausgegangen, dass Operationen wie bspw.
Code:
["A","B"] + [42]
ein Array erzeugen, das als Type den "kleinsten gemeinsamen Nenner" aller Elemente besitzt (im Beispiel also Object).

Heißt das jetzt im Klartext, dass das ein Bug seitens der Sprache ist? Oder dass sich Mark Sibly etwas dabei gedacht hat?

Edith sagt: Man sollte den kleinsten gemeinsamen Nenner nicht mit dem größten gemeinsamen Teiler verwechseln.
  • Zuletzt bearbeitet von Tritium am Sa, Nov 19, 2011 23:26, insgesamt einmal bearbeitet

ZEVS

BeitragSa, Nov 19, 2011 23:16
Antworten mit Zitat
Benutzer-Profile anzeigen
1. Man kann Arrays so addieren? Cool...
2. Es gibt keinen kleinsten gemeinsamen Nenner zwischen String und Int, denn Int ist eine der o.g. Ausnahmen (manchmal könnte ich diesen Mark *****! Man kann keine nativen Zahlen in TLists speichern!).
3. Da ist auf jeden Fall ein bug, wenn ein (ich schreibe es jetzt, glaube ich, zum dritten Mal), ein TTimer in einem String[] ist. Der kleinste gemeinsame Nenner wäre auf jeden Fall Object, das interessiert BMax aber nicht.
Interessanterweise ist es nicht möglich, bei der Deklaration eines Object[]s, Werte verschiedener Typen anzugeben. Man muss sie alle einzeln, manuell casten.

Für dein Problem sehe ich keine native Lösung durch casten... Schade.
ZEVS
 

Tritium

BeitragSa, Nov 19, 2011 23:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Tja, dann bleibt mir wohl tatsächlich nur die Schleife, allerdings ohne EachIn, wenn ich das jetzt richtig verstanden habe.

Ich find es echt schade, dass eine Sprache, die so viele Vorzüge bietet, gleichzeitig auch solche Kinderkrankheiten nicht ablegen kann.

Übrigens finden sich in der Hilfe unter "Language Reference" in den Unterpunkten "Arrays", "BASIC Compatibility" und "Slices" noch mehr solcher Operationen.
 

Tritium

BeitragDi, Nov 22, 2011 12:55
Antworten mit Zitat
Benutzer-Profile anzeigen
So, hier nochmal abschließend eine kurze Funktion, die ich mir grad geschrieben hab:

BlitzMax:
Strict

Framework BRL.Blitz
Import BRL.LinkedList
Import BRL.StandardIO


Local list:TList = CreateList()
ListAddLast(list,"Hans")
ListAddLast(list,"Dieter")
ListAddLast(list,CreateList())
ListAddLast(list,"Horst")


Print
For Local temp$ = EachIn StringArray(list,False)
Print temp
Next

End


Function StringArray$[](list:TList,stringsOnly=True)
If Not list Then Return Null
Local array$[] = New String[CountList(list)]

If stringsOnly Then
Local i = 0
For Local obj:Object = EachIn list
array[i] = String(obj)
i :+ 1
Next
Else
Local i = 0
For Local obj:Object = EachIn list
array[i] = obj.toString()
i :+ 1
Next
EndIf

Return array
End Function


Gibt's Verbesserungsvorschläge, was die Geschwindigkeit angeht?
  • Zuletzt bearbeitet von Tritium am Di, Nov 22, 2011 15:05, insgesamt einmal bearbeitet

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group