6

Community. I need to accept multiple comma-separated inputs to produce a summary of information ( specifically, how many different employees participated in each group/project)? The program takes employees, managers and groups in the form of strings.

I'm using anytree python library to be able to search/count the occurrence of each employee per group. However, this program is only accepting one value/cell at a time instead of multiple values.

Here is the tree structure and how I accept input values?

Press q to exit, Enter your data: Joe
Press q to exit, Enter your data: Manager1
Press q to exit, Enter your data: Group1
Press q to exit, Enter your data: Charles 
Press q to exit, Enter your data: Manager1
Press q to exit, Enter your data: Group2
Press q to exit, Enter your data: Joe
Press q to exit, Enter your data: Manager3
Press q to exit, Enter your data: Group1
Press q to exit, Enter your data: Charles
Press q to exit, Enter your data: Manager3
Press q to exit, Enter your data: Group1
Press q to exit, Enter your data: Joe
Press q to exit, Enter your data: Manager5
Press q to exit, Enter your data: Group2
Press q to exit, Enter your data: q
Employee   No of groups
   JOE       2
   CHARLES       2
Group
├── GROUP1
│   ├── JOE
│   │   └── MANAGER1
│   ├── JOE
│   │   └── MANAGER3
│   └── CHARLES
│       └── MANAGER3
└── GROUP2
    ├── CHARLES
    │   └── MANAGER1
    └── JOE
        └── MANAGER5

I need help with this code so that It can accept comma-separated values; for example, to enter Joe, Manager1, Group1 at a time.

import anytree

from anytree import Node, RenderTree, LevelOrderIter, LevelOrderGroupIter, PreOrderIter

import sys

# user input
io=''
lst_input = []
while (io!='q'):
    io=input('Press q to exit, Enter your data: ')
    if io!='q':
        lst_input.append(io.upper())

# change list in to matrix
lst=[]
for i in range(0, len(lst_input), 3):
    lst.append(lst_input[i:i + 3])

lst

# create tree structure from lst
group = Node('Group')
storeGroup = {}
for i in range(len(lst)):
    if lst[i][2] in [x.name for x in group.children]: # parent already exist, append childrens
        storeGroup[lst[i][0]] = Node(lst[i][0], parent=storeGroup[lst[i][2]])
        storeGroup[lst[i][1]] = Node(lst[i][1], parent=storeGroup[lst[i][0]])
    else: # create parent and append childreds
        storeGroup[lst[i][2]] = Node(lst[i][2], parent=group)
        storeGroup[lst[i][0]] = Node(lst[i][0], parent=storeGroup[lst[i][2]])
        storeGroup[lst[i][1]] = Node(lst[i][1], parent=storeGroup[lst[i][0]])


store = {}
for children in LevelOrderIter(group, maxlevel=3):
    if children.parent!=None and children.parent.name!='Group':
        if children.name not in store:
            store[children.name] = {children.parent.name}
        else:
            store[children.name] = store[children.name] | {children.parent.name}

print('Employee', '  No of groups')
for i in store:
    print('   '+i+'      ', len(store[i]))


for pre,fill, node in RenderTree(group):
    print('{}{}'.format(pre,node.name))


Thank you! Any thoughts are welcomed.

kibromhft
  • 911
  • 1
  • 7
  • 18

3 Answers3

5

Leverage unpacking to extract elements. Then the if statement can be re-written this way.

if io!='q':
    name, role, grp = io.upper(). split(',')
    lst_input.append([name,role, grp]) 

you also need to change lst.append(lst_input[i:i + 3]) in the for loop to this.

lst.append(lst_input[0][i:i + 3])
codingera
  • 206
  • 1
  • 3
3

I believe one way to go about it is:

name, role, grp = io.upper().split(',')

which for an input such as Joe, Manager1, Group1

Python 3.7.9 (v3.7.9:13c94747c7, Aug 15 2020, 01:31:08)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

>>> name, role, grp = input("Press q to exit, Enter your data:").split(",")
Press q to exit, Enter your data:Joe, Manager1, Group1
>>> name
'Joe'
>>> role
' Manager1'
>>> grp
' Group1'

Would that work for you ?

Paulo
  • 8,690
  • 5
  • 20
  • 34
2

Your lst output is something like:

[['Joe', 'Manager1', 'Group1'], ['Charles', 'Manager1', 'Group2'], ['Joe', 'Manager3', 'Group1'], ['Charles', 'Manager3', 'Group1'], ['Joe', 'Manager5', 'Group2']]

The below code makes the same lst output with a much better performance:

import anytree

from anytree import Node, RenderTree, LevelOrderIter, LevelOrderGroupIter, PreOrderIter

import sys

# user input
lst = []
while True:
   io=input('Press q to exit, Enter your data: ')
   if io!='q':
      lst.append(io.upper().split(',')) 
   else:
      break
print(lst)

# create tree structure from lst
group = Node('Group')
storeGroup = {}
for i in range(len(lst)):
    if lst[i][2] in [x.name for x in group.children]: # parent already exist, append childrens
        storeGroup[lst[i][0]] = Node(lst[i][0], parent=storeGroup[lst[i][2]])
        storeGroup[lst[i][1]] = Node(lst[i][1], parent=storeGroup[lst[i][0]])
    else: # create parent and append childreds
        storeGroup[lst[i][2]] = Node(lst[i][2], parent=group)
        storeGroup[lst[i][0]] = Node(lst[i][0], parent=storeGroup[lst[i][2]])
        storeGroup[lst[i][1]] = Node(lst[i][1], parent=storeGroup[lst[i][0]])


store = {}
for children in LevelOrderIter(group, maxlevel=3):
    if children.parent!=None and children.parent.name!='Group':
        if children.name not in store:
            store[children.name] = {children.parent.name}
        else:
            store[children.name] = store[children.name] | {children.parent.name}

print('Employee', '  No of groups')
for i in store:
    print('   '+i+'      ', len(store[i]))


for pre,fill, node in RenderTree(group):
    print('{}{}'.format(pre,node.name))

Defining a lot of unnecessary lists in your original code will ruin your performance. Even avoid doing the extra comparision or defining unnecessary variables. Note that we don't have do ... while structure in Python. So, we use break to avoid doing duplicate comparision.

Happy Ahmad
  • 1,072
  • 2
  • 14
  • 33