TList - ToStringArray()

BlitzMax Forums/BlitzMax Programming/TList - ToStringArray()

Henri(Posted 2014) [#1]
Curious, is TList missing a "ToStringArray()" method ?

This doesn't seem to work:
SuperStrict

Local list:TList = New TList
list.addlast("one")
list.addlast("two")
list.addlast("three")

Local ar:String[] = String[](list.ToArray())

Print "Length of array = " + ar.length

For Local s:String = EachIn ar
	Print s
Next


-Henri


Brucey(Posted 2014) [#2]
ar is empty because of your cast to String[].
ToArray() returns an Object[], which you can still iterate over to get your strings :
SuperStrict

Local list:TList = New TList
list.addlast("one")
list.addlast("two")
list.addlast("three")

Local ar:Object[] = list.ToArray()

Print "Length of array = " + ar.length

For Local s:String = EachIn ar
	Print s
Next



Henri(Posted 2014) [#3]
But I can't use object array as an parameter to a function which expects string array as a parameter without converting it first, which seems unnecessary overhead.

-Henri


Henri(Posted 2014) [#4]
This seems better:
Strict

Local list:mylist = New mylist
list.addlast("one")
list.addlast("two")
list.addlast("three")

Local ar:String[] = list.ToStringArray()

Print "Length of array = " + ar.length

For Local s:String = EachIn ar
	Print s
Next

Type mylist Extends TList

	Rem
	bbdoc: convert a list to an array
	returns: An array of strings
	End Rem
	Method ToStringArray:String[]()
		Local arr:String[Count()],i
		Local link:TLink=_head._succ
		While link<>_head
			arr[i]=String(link._value)
			link=link._succ
			i:+1
		Wend
		Return arr
	End Method
EndType


-Henri


TomToad(Posted 2014) [#5]
There is a small bug with your code. If you have anything non-string in the list, the array will be filled with Null strings. I've modified it a bit so only strings will be added to the array, and non-strings will be skipped.



Henri(Posted 2014) [#6]
Yes, it's the age old question; To check or not to check ? :-)

Argument against checking:

1. It might be not a good idea to populate list with mixed string and other objects in the first place. An empty string is a visible placeholder for something that was error in the beginning.

2. You can also check empty strings afterwards if so desired

3. It's faster ?


-Henri


TomToad(Posted 2014) [#7]
1. It might be not a good idea to populate list with mixed string and other objects in the first place. An empty string is a visible placeholder for something that was error in the beginning.

There are many reasons why you want to mix objects in a type. You may have special formatting objects mixed with the strings. If you want to later print the strings without the formatting, you could use ToStringArray() to get only the strings

2. You can also check empty strings afterwards if so desired

To find the Null strings and move the elements in the array to fill in the empty space will be more computational expensive than a single if statement

3. It's faster ?

It is only slightly faster if you can guarantee that all the elements will be strings.

Of course, at the end of the day, which is best depends on what you are using it for. If you intend to use the list for only strings, it may be better to check before it is even entered into the list. Below, I changed the name of your type from mylist to StringList (makes more sense to me) and overridden the AddLast method
Type StringList Extends TList

	Rem
	bbdoc: convert a list to an array
	returns: An array of strings
	End Rem
	Method ToStringArray:String[]()
		Local arr:String[Count()],i
		Local link:TLink=_head._succ
		While link<>_head
			arr[i]=String(link._value)
			link=link._succ
			i:+1
		Wend
		Return arr
	End Method
	
	Method addlast:TLink(s:Object)
		If String(s) = Null
			RuntimeError("Cannot add Null or non-string object to StringList")
		End If
		Return Super.addlast(s)
	End Method
EndType


There is a bug I can't resolve. You cannot explicitly enter an empty string as BlitzMAX treats empty strings and Null strings as the same. The only way I found around that would be to do List.AddLast(Chr(0)).