[Closed] How to convert a file into an array with sublevels ?
Hi guys,
Let us say that I define an array in a file.
the file:
(
a1
a2
(
b1
b2
(
c1
c2
)
b3
)
a3
(
b4
(
c3
)
b5
)
)
For practical reasons, I converted this file into an linear array:
thefile=#("(","a1", "a2", "(", "b1", "b2", "(", "c1", "c2", ")", "B3", ")", "a3", "(", "b4", "(", "c3", ")", "b5", ")",")")
Now I would like to transform this file into an array with sublevels.
Here the expected result written by hand:
#(a1,a2,#(b1,b2,#(c1,c2),b3),a3,#(b4,#(c3),b5))
How do you make that ?
I tested several recursive functions but without success.
Of course I cannot just add # in front of ( and some commas
Can anyone point me in the right direction ? Thanks
heres some pretty basic pseudocode to get you going:
new array anArray
position = 0
while (elt != flag)
(
anArray append elt
elt = getElement file position != flag
)
getElement file possition
(
if token file position == “(” then
(
new array2
while token file position != “)”
(
advance position
array2.append token
)
return array2
) else
return token
)
This code is pretty similar to the functions that I have tried.
But there are no recursive logic and because of that the array is not yet correct.
Test this code:
fn readBloc array pos =
(
if pos>array.count
then false
else (
end=pos
bloc=0
do (
if array[end]=="(" then bloc+=1
if array[end]==")" then bloc-=1
end+=1
)
while ( bloc>0 and end<=array.count )
if pos==(end-1)
then array[pos]
else ( newArray=for i=pos to (end-1) collect array[i] )
)
)--fn
fn getArrayFromPseudoFile pseudoFile =
(
newArray=#()
position=1
element=true
while element!=false do
(
element=readBloc pseudoFile position
if element!=false do append newArray element
if classof element==Array
then position+=element.count
else position+=1
)--while
format "
newArray=%
" newArray
format "
print newArray
"
print newArray
format "
===========
"
)--fn
clearListener()
pseudoFile=#("a1", "a2", "(", "b1", "b2", "(", "c1", "c2", ")", "b3", ")", "a3", "(", "b4", ")","a4")
getArrayFromPseudoFile pseudoFile
the array:
a1
a2
(
b1
b2
(
c1
c2
)
b3
)
a3
(
b4
)
a4
The function return this array:
newArray=#("a1", "a2", #("(", "b1", "b2", "(", "c1", "c2", ")", "b3", ")"), "a3", #("(", "b4", ")"), "a4")
print newArray
"a1"
"a2"
#("(", "b1", "b2", "(", "c1", "c2", ")", "b3", ")")
"a3"
#("(", "b4", ")")
"a4"
As you can see the result is not yet correct.
Nevertheless Thanks for your help. It is a step moreover towards the solution.
It misses a recursive logic.
Does somebody have an idea?
I have just found a solution.
fn arrayTransformer array =
(
pos=1
startBloc=0
while ( array[pos]!=")" and pos<=array.count) do
(
if array[pos]=="(" do startBloc=pos
pos+=1
)
if startBloc==0 then false
else (
startArray=for i=1 to startBloc-1 collect array[i]
blocArray=for i=startBloc+1 to pos-1 collect array[i]
endArray=for i=pos+1 to array.count collect array[i]
startArray+#(blocArray)+endArray
)
)--fn
fn arrayStructureFinder array =
(
retValue=array
do (
array=retValue
retValue=arrayTransformer array
)
while retValue!=false
array
)--fn
pseudoFile=#("a1", "a2", "(", "b1", "b2", "(", "c1", "c2", ")", "b3", ")", "a3", "(", "b4", ")","a4")
structuredArray=arrayStructureFinder pseudoFile
clearListener()
format "structuredArray=%
" structuredArray
It requires many manipulations in memory.
I do not think that it is the ideal solution… but It works.
If somebody has a better method. I am still interested to know it.
Have a good day.
I’ts inefficient because you uneccessarily make many copies of the array.
You should make one function that can return either an element or an array. This function should call itself in order to find the next element if it’s going to be returning an array.
In the place where I wrote “array2.append token”, if you replace that with a call to “getElement” then it will be recursive and the concept of it will work.
Ok I restart from the begining.
If you help me a bit, I could write an optimized script.
First I convert your pseudo code in maxscript.
I make some modifications.
I add the variable ‘bloc’ to avoid an error : the function would return
an incomplete structure if it stopped with the first “)”
ok after that getElement return:
getElement pseudoFile 2
==> "a2"
getElement pseudoFile 6
==> #("c1", "c2")
getElement pseudoFile 3
==> #("b1", "b2", "(", "c1", "c2", ")", "b3")
There is not yet an recursive logic. But do you agree with the results ?
The script:
fn getElement array position =
(
if position>array.count then false
else
(
if array[position]=="("
then (
position+=1
bloc=1
array2=#()
while ( bloc>0 and position<=array.count ) do
(
append array2 array[position]
position+=1
if array[position]=="(" then bloc+=1
if array[position]==")" then bloc-=1
)
array2
)
else array[position]
)
)
pseudoFile=#("a1", "a2", "(", "b1", "b2", "(", "c1", "c2", ")", "b3", ")", "a3", "(", "b4", ")","a4")
anArray=#()
position=1
count=1
elt=getElement pseudoFile position
while (elt != false) do
(
if classof elt==Array then position+=elt.count else position+=1
append anArray elt
elt=getElement pseudoFile position
)
format "anArray=%
" anArray
The next step is to add the recursive call.
I have just found the code recursive
fn arrayFromFile array pos =
(
newArray=#()
while pos<=array.count do
(
if ( array[pos]!="(" and array[pos]!=")" )
then (append newArray array[pos])
else (
if array[pos]=="(" do
(
nextPos=pos+1
pos+=1
bloc=1
array2=#()
while ( bloc>0 and pos<=array.count ) do
(
append array2 array[pos]
pos+=1
if array[pos]=="(" then bloc+=1
if array[pos]==")" then bloc-=1
)
append newArray (arrayFromFile array2 1)
)
)
pos+=1
)
newArray
)
clearListener()
pseudoFile=#("a1", "a2", "(", "b1", "b2", "(", "c1", "c2", ")", "b3", ")", "a3", "(", "b4", ")","a4")
structuredArray=arrayFromFile pseudoFile 1
format "structuredArray=%
" structuredArray
stuh505 thanks for your help. You pointed me in the right direction.
Here’s a more concise way of doing it. By the way you don’t need to use recursion, you could use a list to store temporary lists as a kind of stack. How do you paste code with indentation?
fn sublevelarray list=
(
pos=0
return (getNextSublevel list)
)
fn getNextSublevel list =
(
pos+=1
if (pos > list.count) then
return
if (list[pos]==")") then
return ")"
if (list[pos]=="(") then
(
newArray=#()
while ((ret = getNextSublevel list) != ")") do
append newArray ret
return newArray
)
return list[pos]
)
myarray=#(“(“,“1”,“2”,”(“,“3”,“4”,”)”,”)”)
sublevelarray myarray
EDIT: I wrote mine to deal with an original list that has “(” and “)” at the front and back
Oh easy. I copy/paste from maxscript editor. I select my script and press # in toolmenu of the post editor. That adds the header ‘CODE’ to keep the indentation.
[CO_DE]code with identation[/CO_DE] (remove the “_”)
1
2
3
If you use an another editor, try this to remove the special format: open notepad and press CTRL+V(paste),CTRL+A(select all),CTRL+X(cut)
Could you post your code with indentation ?
Thanks
fn sublevelarray list=
(
pos=0
return (getNextSublevel list)
)
fn getNextSublevel list =
(
pos+=1
if (pos > list.count) then
return
if (list[pos]==")") then
return ")"
if (list[pos]=="(") then
(
newArray=#()
while ((ret = getNextSublevel list) != ")") do
append newArray ret
return newArray
)
return list[pos]
)
myarray=#("(","1","2","(","3","4",")",")")
sublevelarray myarray