PDA

View Full Version : Array Left$



ReneMiner
28-10-2015, 22:13
Currently I try to find a fast method to scan some dynamic string-array for just a part of the string to create some auto-complete-stuff.

So I have a dynamic string-array containing all the keywords.

Now when the user types for example the letters "func" - it's obvious that he wants to type either "Function", "Function_CParams" or something like that so i want my script make to suggest this.

The solution were some Array-method that works a little bit as Array Scan myArray, Collate Ucase, = "func" but i imagine more like



Dim sourceArray() As String
Dim destinationArray() As String

Dim sFile as String = "c:\thinBasic\thinAir\Syntax\thinBasic\thinBasic_Keywords.ini"
Dim nKeywords, nMatches As Long

nKeywords = Parse File sFile, sourceArray, $CRLF
'...

nMatches = Array sourceArray, Left$ = "FUNC" [, Collate Ucase] To destinationArray


where it performs a complete array scan on sourceArray() and all members of sourceArray that match "FUNC" will be collected in destinationArray().
Array-members thats length is less then "FUNC" should not cause error.
Syntax above is just for better understanding what i mean.
Instead of "Left$" it could be named however you like



nMatches = Array Select sourceArray, StartsWith "FUNC", Collate Ucase To destinationArray


alternative it could return an array of indexes - or just work as the current Array Scan-way



Long lStart, lPos
Do
lPos = Array Scan sourceArray(lStart+1), Collate Ucase, StartsWith "FUNC"
If lPos = 0 Then Exit Do
'... do something with matching element
'... go for the next one....
lStart += lPos
Loop


StartsWith/EndsWith (both are keywords already) in that case were only a switch as "=", "<=" etc.
Of course only valid to scan for strings.
If possible it could also Array Scan Ptr for elements that StartsWith/EndsWith
i just care for functionality :)

ErosOlmi
29-10-2015, 21:12
It's on the go.
I like it in both the syntax you suggested.

I'm just thinking what's the best way to implement.

ErosOlmi
29-10-2015, 22:12
What about the following syntax:


nItems = ARRAY EXTRACT mainArray(), StartsWith | EndsWith | Like (regular expression string) [, Collate ...] InTo destinationArray

nItems will contain the number of elements found
mainArray will be automatically sorted
destinationArray will automatically free and re-dimensioned

Like comparison will use regular expressions already valid for REGEXPR$. Anyway still to think how to do this one.

ReneMiner
29-10-2015, 23:35
reads good

Into :)


a keyword with a bright future... should make more use of it.

inMyPockets = [Module]_PutStuff [source [,condition1 [, condition2...]]] Into myPockets()

ReneMiner
30-10-2015, 08:40
...
mainArray will be automatically sorted
...


i'm not sure if this is necessary to sort the keywords again on each call.
Perhaps suggest in help to sort the array previously for best results, but if it's sorted once...:confused:

ErosOlmi
31-10-2015, 11:24
Development done.
New functionality will be present in next 1.9.16 version that I will publish by tomorrow (or before if I finish few things)

Syntax will be the following:


ARRAY EXTRACT MainArray, [COLLATE UCASE,] {StartsWith | EndsWith | Contains} ComparisonStringExpression InTo DestinationArray
Example:


Uses "Console"

Dim sourceArray() As String
Dim destinationArray() As String
Dim nKeywords, nMatches, nCount As Long

nKeywords = Parse APP_ListKeywords($CRLF), sourceArray, $CRLF

nMatches = Array extract sourceArray(), Collate Ucase, StartsWith "FUNC" inTo destinationArray

PrintL "Found:", nMatches
For nCount = 1 To nMatches
PrintL nCount, destinationArray(nCount)
Next

WaitKey

ReneMiner
31-10-2015, 11:34
nnnnnnice :D


Development done.
New functionality will be present in next 1.9.16 version that I will publish by tomorrow (or before if I finish few things)

Syntax will be the following:


ARRAY EXTRACT MainArray, [COLLATE UCASE,] {StartsWith | EndsWith | Contains} ComparisonStringExpression InTo DestinationArray


Would it also be possible to do this:


ARRAY EXTRACT pArray PTR , [COLLATE UCASE,] {StartsWith | EndsWith | Contains} ComparisonStringExpression InTo DestinationArray


?
the chair i'm sitting on seems to burn :excited:

ErosOlmi
31-10-2015, 13:15
Not in this release but if it is working fine with standard string arrays, it is quite easy to add arrays of pointers.
So first check this and soon I will add the PTR version.

Updated 1.9.16 is already into the link you know.

Just test it and if OK I will work for the tomorrow public release.

ReneMiner
31-10-2015, 14:04
bad news: scripts don't run no more - an optional function-parameter gets lost within a function:

this one of my type-functions:


'-------------------------------------------------------------------
Function TextSet(ByVal sText As String, _
Optional ByVal lLine As Long _
) As String
'-------------------------------------------------------------------

the variable lLine is used a few times succesfully...
100 lines of code further, in same function follows this


'...
If lLine < 1 Then
' ...

Error Code 30
Variable not defined or misspelled Keyword

Token found: lLine

- script as is was running a few minutes ago using the previous tB 1.9.16 alpha

ErosOlmi
31-10-2015, 14:11
Strange, here optional parameters seems working just fine.
I did'n change anything on that matter.

I worked on FOR/NEXT maybe is in this area.

I will check but I need a simple example showing the problem.

ReneMiner
31-10-2015, 14:19
exactly that:



Uses "console"


Type tBase
pText As DWord

'-------------------------------------------------------------------
Function TextSet(ByVal sText As String, _
Optional ByVal lLine As Long _
) As String
'-------------------------------------------------------------------

' set either all text (no line-number)
' or replace a certain line if lLine exists
' negative lLine = simply append text

Local pLine() As DWord At 0
Local sLine() As String
Local i, nLines As Long

nLines = Parse sText, sLine, $CRLF


If Not lLine Then
' no line-number, so sText is completely new text

If HEAP_Size(Me.pText) >= 4 Then
ReDim pLine(HEAP_Size(Me.pText)/4) At Me.pText
For i = 1 To UBound(pLine)
HEAP_Free(pLine(i))
Next
EndIf

If nLines Then
Me.pText = HEAP_ReAllocByStr(Me.pText, Repeat$(nLines, MKDWD$(0)) )
ReDim pLine(nLines) At Me.pText
For i = 1 To nLines
pLine(i) = HEAP_AllocByStr(sLine(i))
Next
Else
HEAP_Free(Me.pText)
Me.pText = 0
EndIf
Else
If HEAP_Size(Me.pText) >= 4 Then
ReDim pLine(HEAP_Size(Me.pText)/4) At Me.pText

If Between(lLine, 1, UBound(pLine)) Then
' replace lLine with new sText
Select Case nLines
Case 0
HEAP_Free(pLine(lLine))
pLine(lLine) = 0

Case 1
pLine(lLine) = HEAP_ReAllocByStr(pLine(lLine), sLine(1))

Case Else
If lLine + (nLines - 1) > UBound(pLine) Then
Me.pText = HEAP_ReAllocByStr(Me.pText, HEAP_Get(Me.pText) & Repeat$(lLine + (nLines - 1) - UBound(pLine), MKDWD$(0)) )
ReDim pLine(HEAP_Size(Me.pText)/4) At Me.pText
EndIf
For i = 1 To nLines
pLine(i + lLine - 1) = HEAP_AllocByStr(sLine(i))
Next
End Select
Else
' lLine is out of current range
If lLine < 1 Then
' simply append it

lLine = UBound(pLine)
Me.pText = HEAP_ReAllocByStr(Me.pText, HEAP_Get(Me.pText) & Repeat$(nLines, MKDWD$(0)))
ReDim pLine(HEAP_Size(Me.pText)/4) At Me.pText
For i = 1 To nLines
pLine(i + lLine) = HEAP_AllocByStr(sLine(i))
Next
Else
' insert empty lines until all available
Me.pText = HEAP_ReAllocByStr(Me.pText, HEAP_Get(Me.pText) & Repeat$(lLine + (nLines - 1) - UBound(pLine), MKDWD$(0)) )
ReDim pLine(HEAP_Size(Me.pText)/4) At Me.pText
For i = 1 To nLines
pLine(i + lLine - 1) = HEAP_AllocByStr(sLine(i))
Next
EndIf

EndIf
Else
' Me.pText is empty
Me.pText = HEAP_AllocByStr(Repeat$(nLines, MKDWD$(0)) )
ReDim pLine(HEAP_Size(Me.pText)/4) At Me.pText
For i = 1 To nLines
pLine(i) = HEAP_AllocByStr(sLine(i))
Next

EndIf
EndIf

Function = sText
End Function


End Type

Function TBMain()
Local x As tBase

PrintL x.TextSet( "Hello" & $CRLF _
& "this" & $CRLF _
& "is a" & $CRLF _
& "test" )

PrintL
PrintL "---Press a key to finish---"
WaitKey
End Function





EDIT: missing parenthesis corrected (2 times, lines 60, 73 or 80)

ErosOlmi
31-10-2015, 14:35
OK, got example and able to reproduce the problem.
I'm checking.

ReneMiner
31-10-2015, 14:44
i'm going to visit my girlfriend in hospital now... be back in the evening

ErosOlmi
31-10-2015, 14:51
Thanks for helping me.
It will be a bit long to solve this, it is related to IF/ELSE/END IF nesting level.

ErosOlmi
31-10-2015, 20:12
I think I've fixed the problem.
Uploaded an updated 1.9.16.0
Let me know.

Ciao
Eros

ReneMiner
31-10-2015, 21:06
came not far enough to test Array Extract yet but thinAir bugs again (see mail from last week)

ErosOlmi
31-10-2015, 21:11
Yes, didn't had time to see all your reports but will check next days.
Work load will be a little lower next few weeks so I think to have some time to go on to fix and develop new features.

Actually I'm interested to know if today bug is solved.

ReneMiner
31-10-2015, 22:04
todays bug seems solved. Also Array Extract works really nice & fast

btw. Found duplicate keyword in thinBasic_Keywords.ini

ACCELAPI

ErosOlmi
31-10-2015, 22:10
Great.

It is a predefined UDT: http://www.thinbasic.com/public/products/thinbasic/help/html/index.html?accelapi.htm
Maybe I've defined twice.
I will check where

If more UDT having the same name are defined in different places but they are are structured the same, thinBasic does not complain.

ErosOlmi
31-10-2015, 22:23
I need your opinion.

Regarding PTR option (it means mainArray is an array of pointers to string) ...
do you think also DestinationArray MUST be a PTR array or only source should be?

ReneMiner
31-10-2015, 23:06
i think it's ok to have the result in a common dynamic string-array- mostly local within a function anyway.

It's up to the user now to pass the whole array to another function or to store it @heap if needed

ErosOlmi
01-11-2015, 13:52
Added PTR version of ARRAY EXTRACT in public 1.9.16.x

Ciao
Eros

ReneMiner
11-11-2015, 14:24
regarding new Keyword Into:

i like how it reads... and it's very clear what it does.

In a certain sense it's the reverse operation to variadic function-parameters... :lol:


Can we have Into useable for tB-script-functions too
Byref passed array-variable that can be dimensioned locally on the fly ?

Example
(tType be any Type of variable or udt)




'... "Into" could work like "ByRef" here,
' but signals an array-variable [with certain dimensions] will follow:

Function putStuff( Into X(~[dim1[, dim2[, dim3]]]~) As tType[, more parameters....]) As Long

' x be the array-varriable

' ~[dim1[, dim2[, dim3]]]~ not supposed to be written by the user as in line further above
' = dimensions bounds,

' "Into x() As tType" (empty parenthesis, no bounds) will serve,
' since Ubound(x, 2) = 0 if x has no 2nd dimension...

' if passed dim1[, dim2[, dim3]] on the call : (see below)
' fixed array size
' or 1-dimensional dynamic, contains already dim1 elements
' else
' x will be dynamic and contains 0 elements
' Endif
End Function


' equals:



Function putStuff( ByRef X() As tType[, more parameters....]) As Long

' no change necessary, only allow Alias ByRef As Into for this
End Function

' call :

Long l = putStuff( [Into|Preserve] myData[([dim1[, dim2[, dim3]]])[ As tType]][, more parameters...] )
' enable instant (re-)dimensioning and passing ByRef within function-call,


' If <"Into" present> Then
' ~~~ make a new, empty barrel for stuff to put into
' If variable_exists(myData) Then
' Redim myData([dim1[, dim2[, dim3]]])
' Else
' Dim myData([dim1[, dim2[, dim3]]]) [As tType]
' Endif

' ElseIf Variable_Exists(myData) Then
' ~~~ check for valid bounds
' If Not <"dim3" present> Then
' If Ubound(myData, 3) > 0 Then
' Long dim3 = Ubound(myData, 3) ~~~ assume we check for existance later
' EndIf
' If Not <"dim2" present> Then
' If Ubound(myData, 2) > 0 Then
' Long dim2 = Ubound(myData, 2)
' EndIf
' If Not <"dim1" present> Then
' If Ubound(myData, 1) > 0 Then
' Long dim1 = Ubound(myData, 1)
' Endif
' EndIf
' EndIf
' EndIf

' If <"Preserve" present> Then
' ~~~ obvious
' Redim Preserve myData([dim1[, dim2[, dim3]]])
' EndIf
' EndIf

' pass BYREF myData[(dim1[, dim2[, dim3]])][, more parameters...]> to function putStuff(...)

' finally real code reads as:
Local numBugs As Long = CollectBugs( Into myBuglist() As String )
' now i have a dimensioned - and hopefully empty - local array myBuglist



[post moved over here to keep other thread on topic]