Split string to multidimensional (2D) array - arrays

I try to split a string into a multidimensional array, but it is not working the way I want. I just split a string to some arrays where one 2 dimensional array should represent a table. I can see the array using _ArrayDisplay() but I cannot work with the array elements itself. The Line:
For $j = 1 To $aTable1Row[$i][0]
reports "incorrect number of subscripts". But if I do:
MsgBox(1, "TEST", UBound($aTable1Row[$i]))
it shows this array has 8 elements. So they are there but I somehow cannot access them. Full source code:
#include <Array.au3>
$string = "az#1:y#2:x#3:w#4:v#5:u#6:t#7-bz#1:y#2:x#3:w#4:v#5:u#6:t#7-cz#1:y#2:x#3:w#4:v#5:u#6:t#7"
$aTable1 = StringSplit($string, '-',1)
_ArrayDisplay($aTable1)
;3
;az#1:y#2:x#3:w#4:v#5:u#6:t#7
;bz#1:y#2:x#3:w#4:v#5:u#6:t#7
;cz#1:y#2:x#3:w#4:v#5:u#6:t#7
Local $aTable1Row[$aTable1[0]+1]
$aTable1Row[0] = $aTable1[0]
For $i = 1 To $aTable1Row[0]
$aTable1Row[$i] = StringSplit($aTable1[$i], ':',1)
_ArrayDisplay($aTable1Row[$i])
;7
;az#1
;y#2
;x#3
;w#4
;v#5
;u#6
;t#7
;do stuff
For $j = 1 To $aTable1Row[$i][0]
$aTable1Row[$i][$j] = StringTrimLeft(($aTable1Row[$i])[$j], StringInStr(($aTable1Row[$i])[$j], '#'))
Next
Next

… this array has 8 elements.
That For -loop addresses a 1 dimensional array as if it were a 2 dimensional one, hence the Array variable has incorrect number of subscripts or subscript dimension range exceeded. -error.
Declare a 2 dimensional array first. Example (no error-checking):
#include <StringConstants.au3>
#include <Array.au3>
Global Const $g_sString = 'az#1:y#2:x#3:w#4:v#5:u#6:t#7-bz#1:y#2:x#3:w#4:v#5:u#6:t#7-cz#1:y#2:x#3:w#4:v#5:u#6:t#7'
Global Const $g_sDelimRow = '-'
Global Const $g_sDelimCol = ':'
Global Const $g_aArray2D = StringSplitToArray2D($g_sString, $g_sDelimRow, $g_sDelimCol)
_ArrayDisplay($g_aArray2D, #ScriptName)
Func StringSplitToArray2D(Const $sString, Const $sDelimiterRow, Const $sDelimiterCol)
Local $aArray1DRows = StringSplit($sString, $sDelimiterRow, $STR_ENTIRESPLIT)
Local $aArray1DCols = StringSplit($aArray1DRows[1], $sDelimiterCol, $STR_ENTIRESPLIT)
Local $aArray2D[ $aArray1DRows[0] + 1 ][ $aArray1DCols[0] + 1 ]
For $i1 = 1 To $aArray1DRows[0]
$aArray1DCols = StringSplit($aArray1DRows[$i1], $sDelimiterCol, $STR_ENTIRESPLIT)
For $i2 = 1 To $aArray1DCols[0]
$aArray2D[$i1][$i2] = $aArray1DCols[$i2]
Next
Next
Return $aArray2D
EndFunc
Consider _FileReadToArray() if stored as text/CSV file. Related.

#include <StringConstants.au3>
#include <Array.au3>
Global Const $g_sString = 'az#1:y#2:x#3:w#4:v#5:u#6:t#7-bz#1:y#2:x#3:w#4:v#5:u#6:t#7-cz#1:y#2:x#3:w#4:v#5:u#6:t#7'
Global Const $g_sDelimRow = '-'
Global Const $g_sDelimCol = ':'
Global Const $g_aArray2D = StringSplit2D($g_sString, $g_sDelimCol, $g_sDelimRow)
_ArrayDisplay($g_aArray2D, #ScriptName)
Func StringSplit2D($sMatches = "Hola-2-5-50-50-100-100|Hola-6-200-200-100-100", Const $sDelim_Item = "-", Const $sDelim_Row = "|")
Local $iValDim_1, $iValDim_2 = 0, $iColCount
Local $aSplit_1 = StringSplit($sMatches, $sDelim_Row, $STR_NOCOUNT + $STR_ENTIRESPLIT)
$iValDim_1 = UBound($aSplit_1, $UBOUND_ROWS)
Local $aTmp[$iValDim_1][0], $aSplit_2
For $i = 0 To $iValDim_1 - 1
$aSplit_2 = StringSplit($aSplit_1[$i], $sDelim_Item, $STR_NOCOUNT + $STR_ENTIRESPLIT)
$iColCount = UBound($aSplit_2)
If $iColCount > $iValDim_2 Then
$iValDim_2 = $iColCount
ReDim $aTmp[$iValDim_1][$iValDim_2]
EndIf
For $j = 0 To $iColCount - 1
$aTmp[$i][$j] = $aSplit_2[$j]
Next
Next
Return $aTmp
EndFunc ;==>StringSplit2D
It is a very stable function and it was used in massive projects, tested millions of times.
Result

Related

Storing numpy.ndarrays from a loop

I am trying to store the numpy.ndarrays defined as x_c, y_c, and z_c for every iteration of the loop:
for z_value in np.arange(0, 5, 1):
ms.set_current_mesh(0)
planeoffset : float = z_value
ms.compute_planar_section(planeaxis = 'Z Axis', planeoffset = planeoffset)
m = ms.current_mesh()
matrix_name = m.vertex_matrix()
x_c = matrix_name[:,0]
y_c = matrix_name[:,1]
z_c = matrix_name[:,2]
I would like to be able to recall the three arrays at any z_value, preferably with reference to the z_value i.e x_c # z_value = 2 or similar.
Thanks for any help!
p.s very new to coding, so please go easy on me.
You have to store each array in an external variable, for example a dictionary
x_c={}
y_c={}
z_c={}
for z_value in np.arange(0, 5, 1):
ms.set_current_mesh(0)
planeoffset = float(z_value)
ms.compute_planar_section(planeaxis = 'Z Axis', planeoffset = planeoffset)
m = ms.current_mesh()
m.compact()
print(m.vertex_number(), "vertices in Planar Section Z =", planeoffset)
matrix_name = m.vertex_matrix()
x_c[planeoffset] = matrix_name[:,0]
y_c[planeoffset] = matrix_name[:,1]
z_c[planeoffset] = matrix_name[:,2]
Please, ensure you call m.compact() before accessing the vertex_matrix or you will get a MissingCompactnessException error. Please, note that it is not the same to store anything in x_c[2] or in x_c[2.0], so choose if your index has to be integers o floats and keep the same type (in this example, they are floats).
Later, you can recall values like this:
print("X Values with z=2.0")
print(x_c[2.0])

LUA getting values from table by using a string

How would I go about compiling values from a table using a string?
i.e.
NumberDef = {
[1] = 1,
[2] = 2,
[3] = 3
}
TextDef = {
["a"] = 1,
["b"] = 2,
["c"] = 3
}
If I was for example to request "1ABC3", how would I get it to output 1 1 2 3 3?
Greatly appreciate any response.
Try this:
s="1ABC3z9"
t=s:gsub(".",function (x)
local y=tonumber(x)
if y~=nil then
y=NumberDef[y]
else
y=TextDef[x:lower()]
end
return (y or x).." "
end)
print(t)
This may be simplified if you combine the two tables into one.
You can access values in a lua array like so:
TableName["IndexNameOrNumber"]
Using your example:
NumberDef = {
[1] = 1,
[2] = 2,
[3] = 3
}
TextDef = {
["a"] = 1,
["b"] = 2,
["c"] = 3
}
print(NumberDef[2])--Will print 2
print(TextDef["c"])--will print 3
If you wish to access all values of a Lua array you can loop through all values like so (similarly to a foreach in c#):
for i,v in next, TextDef do
print(i, v)
end
--Output:
--c 3
--a 1
--b 2
So to answer your request, you would request those values like so:
print(NumberDef[1], TextDef["a"], TextDef["b"], TextDef["c"], NumberDef[3])--Will print 1 1 2 3 3
One more point, if you're interested in concatenating lua string this can be accomplished like so:
string1 = string2 .. string3
Example:
local StringValue1 = "I"
local StringValue2 = "Love"
local StringValue3 = StringValue1 .. " " .. StringValue2 .. " Memes!"
print(StringValue3) -- Will print "I Love Memes!"
UPDATE
I whipped up a quick example code you could use to handle what you're looking for. This will go through the inputted string and check each of the two tables if the value you requested exists. If it does it will add it onto a string value and print at the end the final product.
local StringInput = "1abc3" -- Your request to find
local CombineString = "" --To combine the request
NumberDef = {
[1] = 1,
[2] = 2,
[3] = 3
}
TextDef = {
["a"] = 1,
["b"] = 2,
["c"] = 3
}
for i=1, #StringInput do --Foreach character in the string inputted do this
local CurrentCharacter = StringInput:sub(i,i); --get the current character from the loop position
local Num = tonumber(CurrentCharacter)--If possible convert to number
if TextDef[CurrentCharacter] then--if it exists in text def array then combine it
CombineString = CombineString .. TextDef[CurrentCharacter]
end
if NumberDef[Num] then --if it exists in number def array then combine it
CombineString = CombineString .. NumberDef[Num]
end
end
print("Combined: ", CombineString) --print the final product.

How to use a self made Type in F#?

I made a type, but I don't know how to use it properly and I don't found any solution on google.
type Sample =
{
TrackPosition : int
TubePosition : int
Barcode : string
}
let arraySamples = Array.create Scenario.Samples.NumberOfSamples **Sample**
BarcodeGenerieren.Samples.Sample
let mutable trackPosition = Scenario.Samples.StartTrackPositions
let mutable index = 1
for i in 1 .. Scenario.Samples.NumberOfSamples do
let randomNumber = System.Random().Next(0,9999)
if index > 24 then
trackPosition <- trackPosition + 1
index <- 1
arraySamples.[index] <- **new Sample{TrackPosition= trackPosition, TubePosition = index, Barcode = sprintf "100%s%06d" ((trackPosition + 1) - Scenario.Samples.StartTrackPositions) randomNumber}**
So my question is, what should I changed so that it works, when I will give the type of the array and when I will give the sample with data to the array?
You have created what is referred to as a record type. You can initialise it with the following syntax
{TrackPosition = 0;TubePosition = 0;Barcode = "string"}
your syntax in the last line is almost correct - it should be
arraySamples.[index] <- Sample{
TrackPosition= trackPosition;
TubePosition = index;
Barcode = sprintf "100%s%06d" ((trackPosition + 1) - Scenario.Samples.StartTrackPositions) randomNumber}
The changes are
Eliminate new
replace , with ;

Corona SDK array index is beyond array bounds, advice needed

I will try to as concise as possible with my issue.
Firstly, files are:
block.lua
base.lua
main.lua
In block.lua I create a block, add collision detection and a cleanup code.
In base.lua I create a base made up of 4 columns and 10 rows. 40 blocks in total.
In main.lua I create 4 bases made from the base.class.
All is working fine once the game begins.
I remove the bases and call them again on level 2.
They create themselves ok BUT
when the enemy is destroyed once again, and the bases are to be rebuilt, I get an:
array index 1 is beyond array bounds:1..1
-- all the way up to--
array index 800 is beyond array bounds:1..159
it will then create the bases and continue until the enemys are destroyed and do the same again starting at :
array index 800 is beyond array bounds:1..159
-- all the way up to--
array index 4000 is beyond array bounds:1..159
The terminal points me at block.lua line 23
blockGroup:insert(blockNum,self.block)
Now I cant see anything wrong in the class, I have looked and googled for hours but all to no avail.
I would really appreciate a helping hand to guide me here please.
I have tried rewriting the "cleanup" etc but no joy.
I left a few commented out bits in there and removed some of the irrelevant stuff.
I post below the relevant code:
--MAIN.LUA--
function gameOver()
Runtime:removeEventListener("enterFrame", onEnterFrame)
Runtime:removeEventListener("enterFrame", movePlayer)
layers:removeSelf()
layers = nil
enemyCount = 0
for i = 1,#allEnemys do
timer.cancel(allEnemys[i].clock)
Runtime:removeEventListener( "enterFrame", allEnemys[i] )
display.remove(allEnemys[i].image)
allEnemys[i].image=nil
end
allEnemys=nil
cleanupBlocks()
end
----------------------------------------------------------------------
-- LEVEL UP --
----------------------------------------------------------------------
function levelUp(level)
enemyCount = 0
local enemys = require("modules.enemy")
if allEnemys ~= nil then
for i = 1,#allEnemys do
timer.cancel(allEnemys[i].clock)
Runtime:removeEventListener( "enterFrame", allEnemys[i] )
display.remove(allEnemys[i].image)
allEnemys[i].image=nil
end
end
allEnemys=nil
cleanupBlocks()
levels()
end
----------------------------------------------------------------------
-- LEVELS --
----------------------------------------------------------------------
function levels(level)
function createInvader(x, y, row)
for j = 1, 2 do
for i = 1, 2 do
if allEnemys == nil then
allEnemys = {}
else
enemysCount=#allEnemys
end
allEnemys[#allEnemys + 1] = enemys:new()
allEnemys[#allEnemys ]:init(i * 60, j * 70 + 70,j)
allEnemys[#allEnemys ]:start()
end
end
end
createInvader()
--[[function createBases1()
local base = require("modules.base")
for i = 1, 4 do
base:new()
base:init(i * 180 - 130, 850)
end
end ]]--
createBases()
end
--BLOCK.LUA--
local block = {}
local block_mt = { __index = block}
local scene = scene
local blockGroup = display.newGroup()
local blockNum = 0
function block:new() -- constructor
local group = {}
return setmetatable( group, block_mt )
end
function block:init(xloc,yloc) --initializer
-- Create attributes
self.block = display.newRect( xloc,yloc,10,10)
self.block:setFillColor ( 2, 255, 14 )
blockNum = blockNum + 1
blockGroup:insert(blockNum,self.block)
local blockCollisionFilter = { categoryBits = 128, maskBits = 387}
physics.addBody( self.block, "static", {filter = blockCollisionFilter})
self.count = 1
end
function cleanupBlocks()
--[[ print(blockNum, blockGroup.numChildren)
for i=1,blockGroup.numChildren do
blockGroup[1]:removeSelf()
blockGroup[1] = nil
end ]]--
print(blockNum, blockGroup.numChildren)
while blockGroup.numChildren>0 do
display.remove(blockGroup[1])
blockGroup[1]=nil
end
end
function block:start()
--- Create Listeneres
self.block:addEventListener( "collision", self )
scene:addEventListener('base_block_event', self)
end
return block
--BASE.LUA--
local base = {}
local base_mt = { __index = base}
local scene = scene
local block = require("modules.block")
function base:new() -- constructor
local group = {}
return setmetatable( group, base_mt )
end
function base:init(xloc, yloc) --initializer
-- Create attributes
local base
for j = 1, 4 do
for i = 1, 10 do
base = block:new()
base:init(xloc+i * 10,yloc+j * 10)
base:start()
end
end
end
return base
I see you use
blockNum = blockNum + 1
blockGroup:insert(blockNum,self.block)
Try to use
blockGroup:insert(self.block)
just to see if you still get that error.

Incremental variable definition

I want to automatically define incrementing variable names.
So instead of this:
$Var1 = 'This is variable one :P'
$Var2 = 'This is variable two :P'
I'd like this (pseudo code):
For $i = 1 to UBound($People)-1
**$var[$i]** = GUICtrlCreateCheckbox($var[$i], 24, $y, 200, 17)
$y = $y + 25
Next
Does anyone know how?
The code should make as many checkboxes as defined in an array and every checkbox should have its own variable.
You're looking for the Assign function!
Check out this example:
For $i = 1 To 5
Assign('var' & $i, $i);
Next
Then you can access these variables with:
MsgBox(4096, "My dynamic variables", $var1)
MsgBox(4096, "My dynamic variables", $var3)
MsgBox(4096, "My dynamic variables", $var5)
Obviously, var2 and var3 can be utilised too :)
Edit: For clarity, what you would have been doing, if you had done it properly, was storing those values in an array - which is the best method for this kind of thing.
so instead of this:
$Var1 = 'This is variable one :P'
$Var2 = 'This is variable two :P'
I'd like this (pseudo code):
For $i = 1 to UBound($People)-1
**$var[$i]** = GUICtrlCreateCheckbox($var[$i], 24, $y, 200, 17)
$y = $y + 25
Next
Does anyone know how this could be done?
As per Documentation - Intro - Arrays:
An Array is a variable containing a series of data elements. Each element in this variable can be accessed by an index number which relates to the position of the element within the Array - in AutoIt the first element of an Array is always element [0]. Arrays elements are stored in a defined order and can be sorted.
Dynamic checkbox creation example, assigning multiple checkbox-control identifiers to a single array (untested, no error-checking):
#include <GUIConstantsEx.au3>
Global Const $g_iBoxStartX = 25
Global Const $g_iBoxStartY = 25
Global Const $g_iBoxWidth = 100
Global Const $g_iBoxHeight = 15
Global Const $g_iBoxSpace = 0
Global Const $g_iBoxAmount = Random(2, 20, 1)
Global Const $g_iBoxTextEx = $g_iBoxAmount -1
Global Const $g_sBoxTextEx = 'Your text here.'
Global Const $g_iWindDelay = 50
Global Const $g_iWinWidth = $g_iBoxWidth * 2
Global Const $g_iWinHeight = ($g_iBoxStartY * 2) + ($g_iBoxHeight * $g_iBoxAmount) + ($g_iBoxSpace * $g_iBoxAmount)
Global Const $g_sWinTitle = 'Example'
Global $g_hGUI
Global $g_aID
Main()
Func Main()
$g_hGUI = GUICreate($g_sWinTitle, $g_iWinWidth, $g_iWinHeight)
$g_aID = GUICtrlCreateCheckboxMulti($g_iBoxStartX, $g_iBoxStartY, $g_iBoxWidth, $g_iBoxHeight, $g_iBoxSpace, $g_iBoxAmount)
GUICtrlSetData($g_aID[$g_iBoxTextEx], $g_sBoxTextEx)
GUISetState(#SW_SHOW, $g_hGUI)
While Not (GUIGetMsg() = $GUI_EVENT_CLOSE)
Sleep($g_iWindDelay)
WEnd
Exit
EndFunc
Func GUICtrlCreateCheckboxMulti(Const $iStartX, Const $iStartY, Const $iWidth, Const $iHeight, Const $iSpace, Const $iAmount, Const $sTextTpl = 'Checkbox #%s')
Local $iYPosCur = 0
Local $sTextCur = ''
Local $aID[$iAmount]
For $i1 = 0 To $iAmount -1
$iYPosCur = $iStartY + ($iHeight * $i1) + ($iSpace * $i1)
$sTextCur = StringFormat($sTextTpl, $i1 +1)
$aID[$i1] = GUICtrlCreateCheckbox($sTextCur, $iStartX, $iYPosCur, $iWidth, $iHeight)
Next
Return $aID
EndFunc
GUICtrlCreateCheckboxMulti() demonstrates
array declaration ($aID[$iAmount])
assignment of array elements in a For...To...Step...Next -loop ($aID[$i1] = ...).
Main() demonstrates selection of an individual element (changing its text using GUICtrlSetData()).
Adjust constants as required ($g_iBoxAmount etc.).

Resources