Looping the loops?

Hi

I try to solving the following text file parsing problem.

The script should count the immediate kids of each group based to the number of the tabulators.

In my example the four dots present a one tabulator

Group1
…Group2
… Group3
… Group4
… Object1
… Object2
… Group5
… Group6
… Object3
…Object4
…Object5

Below is same information but presented in target format. The kids number is inside ().

Group1 (1)
Group2 (1)
Group3 (1)
Group4 (4)
Object1 (0)
Object2 (0)
Group5 (2)
Group6 (1)
Object3 (0)
Object4 (0)
Object5 (0)

So, how I can make this happend?

 
path = "D:\\Program Files\\Blender Foundation\\Blender\\.blender\\blends\\myProjects\\WIP scripts\\MyScripts\	ext.txt"

text = open(path,"r")
items = []
depth = []
children = []
lines = text.readlines()

for line in lines:     
    line = line.replace("
","")
    items.append(line.replace(".","").replace(" ",""))    
    depth.append(line.count("...."))    
    children.append(0)    
text.close()
 
for number,item in enumerate(depth):    
    for num in range(number+1,len(depth)):            
        if depth[num] == item+1:
            children[number] += 1            
        elif depth[num] == item:
            break   
     
for i,j in zip(items,children):    
    print "%s (%i)" %(i,j)

It’s probably pretty klunky and someone else can probably do better, but this works for me. I saved your sample as “text.txt” and ran the script outside of Blender. You may need to do some adaptation, and you’ll want to change the path I’ve put in the code, of course.

It prints out this, in my test:

Group1(1)
Group2(1)
Group3(1)
Group4(4)
Object1(0)
Object2(0)
Group5(2)
Group6(1)
Object3(0)
Object4(0)
Object5(0)

Thanks a lot Basil_Fawlty.

Your code work perfectly in python IDLE 8^)

Now I need to study it a bit.

Being lazy, I would just use :


path = c:/t.txt

:smiley:

Here’s a commented version, if that helps. I’m glad it worked. :slight_smile: And IDLE is what I was trying to say, yes.

 
path = "D:\\Program Files\\Blender Foundation\\Blender\\.blender\\blends\\myProjects\\WIP scripts\\MyScripts\	ext.txt"
 
items = [] #a list for names of items in the hierarchy
depth = [] #depth of each item in the hierarchy
children = [] #a list for the number of immediate children of each item in items
 
text = open(path,"r") #fill the lists from the source file
lines = text.readlines()
for line in lines:     
    line = line.replace("
","") #remove line breaks
    items.append(line.replace(".","").replace(" ","")) #add item name to items list   
    depth.append(line.count("....")) #count iterations of our 'tabulator'   
    children.append(0) #prep the children list with all zeroes   
text.close()
 
for number,item in enumerate(depth): #loop through depths to get the number of immediate children   
    for num in range(number+1,len(depth)): #check depths for all items following the current item           
        if depth[num] == item+1: #if depth is one greater than current...
            children[number] += 1 #add to child count           
        elif depth[num] == item: #if depth is same as current, stop counting
            break  #keeps it from counting child-depth items for other parent items 
 
for i,j in zip(items,children): #correlate items and children for the result   
    print "%s (%i)" %(i,j)

You’re not lazy, Mike. You’re efficient. :slight_smile: Nice show on the ActionStrips, BTW. Examples were sorely needed.

Hello Basil_Fawlty

Thanks again for your code.

Now I try to reverse it

From this:
Group1 (1)
Group2 (1)
Group3 (1)
Group4 (4)
Object1 (0)
Object2 (0)
Group5 (2)
Group6 (1)
Object3 (0)
Object4 (0)
Object5 (0)

To this:
Group1
…Group2
… Group3
… Group4
… Object1
… Object2
… Group5
… Group6
… Object3
…Object4
…Object5

I study your code but I can’t get it reversed properly

This is the best result so far. Yes, it’s incorrect.
Group1
…Group2
… Group3
… Group4
… Object1
… Object2
… Group5
… Group6
… Object3
…Object4
…Object5

Any help?:confused:

Can you post the code you’re using to get the current results?

Here is my code draft.


rio = 'f.ac'

rd = open(rio,'r')
oput = open('f.txt','w')

T=0
tabs=0
tabst=0
W=''
name=''
for l in rd:
    data = rd.readline()
    t=''
    OT=''

    if data.find('world') !=-1:
        print 'HI world '
        W='f'
     
    if data.startswith('name') is True:
        #print data
        name = data[6:-2]
    
    if data.startswith('texture') is True:
        t = data

    if  data.startswith('kids') is True:
        tabs = int(data[-3:])
        kids = str(tabs)

        if W =='f':
            tabst=tabs
            st = ('world kids '+kids+'
')
            print st
            W=''
        else:
            tabst = tabst+tabs
        if tabs == 0:
            tab = ('	'*(tabst+1))
            tab = str(tab)
                    
            st=(tab+' '+name+' kids 0
')
            #print st
            
        else:
            tab = ('	'*tabst)
            tab = str(tab)
            tabs = str(tabs)
            st = (tab+' '+name+' kids '+kids+'
')
            #print , name, 'kids',tabs

        oput.write(st)
oput.close()

I try read the AC3D .ac file hierarcy data and put it to the visual structure form. The final target is to add property and texture name data after each group/object name.

(edit)
The first group name reading/writing don’t work right.

 
lines = ["Group1 (1)","Group2 (1)","Group3 (1)","Group4 (4)","Object1 (0)","Object2 (0)","Group5 (2)",
        "Group6 (1)","Object3 (0)","Object4 (0)","Object5 (0)"]
depths = {}
names = []
depth = 0
previous = 0
numkids = (0,0)
for linenum,line in enumerate(lines):
    if line != "":
        split = line.replace(" ","").replace(")","").replace("
","").split("(")
        name = split[0]
        kid = int(split[1])
        if kid != 0:
            numkids = (kid,linenum)
        names.append(name)
        if previous == 0 and linenum-numkids[1] >= numkids[0]+1:
            depth -= 1
        depths[name] = depth
        if kid != 0:
            depth += 1        
        previous = kid
 
tabs = ""
for name in names:    
    tabs = "...." * depths[name]   
    groupname = tabs + name
    print groupname

This at least seems to work (for sorting) with the example you provide. You’ll have to test it with other examples to be sure it will be correct in those cases.
I’m not sure I understand your comment edit. Can you clarify?
I hope the above is helpful. :slight_smile:

On edit:
I spoke too soon. The above only works with the specific example provided. I assume there’s a way to do this, but it’s not as simple as I’d like. :slight_smile: Is this example list of names with numbers of children from your.ac file? Or is the earlier hierarchy example from the .ac file? The problem with the current list is that the parenting is not made very obvious. To fix the depths, it looks like you’ll need the parenting, but you’ll either need a set of rules to discern them from the given list, or you’ll need to work around the problem by gathering the same information from somewhere else (if that’s possible). The rules for determining the parenting hierarchy strat with: “if the number in the previous line is not zero, the current line is the child of the previous line”… but after that I suspect they involve a lot of going back and forth in the list, counting lines and checking indices. I would say, if you’ve created this type of list rather than inheriting it from the .ac file, revise the procedure to include some record of parenting, somehow. It would simplify things…

Still thinking about this, though…

<S> Basil_Fawlty

Thank you for your help.

I was testing the script and your right: The works only with sample Hierarchy Tree (HT).

I attach a link to the zip file, which contains a sample fuel truck game object .ac-file with textures.
http://warezhouze.1g.fi/Here/AC3D/fub2_ac.zip
This object is not made by me.

AC3D .ac Rules? From top of my head.

  • Every AC3D .ac file HT must start with ‘OBJECT world’ and next line tells the number of the kids.

  • The groups are marked with ‘OBJECT group’ line and next line is telling the name ‘name “[name here]”’. Following line/s are telling the properties if exist and last is the number of the kids. There can’t be a kid less groups.

  • The objects (geometries) are marked with ‘OBJECT object or poly’ line and next line is telling the name ‘name “[name here]”’. Next line/s are telling the properties if exist line/s are telling the properties, texture file name, crease value geometry and texturing data and the last is the number of the kids, which must be zero for the object. There can’t be kids for the objects.

It could it’s easier to deal with in these rules. I’m sorry I didn’t provide this info in first case.

The fub2.ac files hierarchy tree as AC3D sees it:


  Group  "WORLD", 1 
          Group  "model", 1 
                  Group  "objects", 1 
                          Group  "fub0", 3 
                                  Group  "l41", 2 
                                          Group  "kl", 2 
                                                  Object "tex0", 0 
                                                  Object "tex1", 0 
                                          Group  "o219", 3 
                                                  Object "tex0", 0 
                                                  Object "tex1", 0 
                                                  Object "tex2", 0 
                                  Group  "l43", 2 
                                          Object "o221", 0 
                                          Object "o222", 0 
                                  Group  "l42", 1 
                                          Object "o220", 0
  

I turned the above hierarchy tree to single string for the script:


  ["world (1)","model (1)","objects (1)","fub0 (3)","l41 (2)","kl (2)","tex0 (0)","tex1 (0)","o219 (3)","tex0 (0)","tex1 (0)","tex2 (0)","l43 (2)","o221 (0)","o222(0)","l42 (1)","o220 (0)"]
  

The script result print-out:


  world
              model
                          objects
                                      fub0
                                                  l41
                                                              kl
                                                                                      tex0
                                                                                      tex1
                                                                          o219
                                                                                      tex0
                                                                                      tex1
                                                                                      tex2
                                                                                      l43
                                                                                                  o221
                                                                                                  o222
                                                                                                  l42
                                                                                                              o220
  

(edit) defined a bit the ‘rules’ part.