Reputation: 320
I have a list of values, for now say tuples, such as
tmis = [
( 'script1', 'function1', 'lock1' ),
( 'script1', 'function2', 'lock1' ),
( 'script1', 'function3', 'lock1' ),
( 'script2', 'function4', 'lock1' ),
( 'script3', 'function5', 'lock2' ),
( 'script4', 'function6', 'lock3' ),
( 'script5', 'function7', 'lock3' ),
( 'script8', 'function10', 'lock1, lock2' )
]
I want to group my data with the same 'script' but with DIFFERENT 'locks'.
Desired output:
[
[('script1', 'function1', 'lock1'),
('script1', 'function2', 'lock1'),
('script1', 'function3', 'lock1'),
('script3', 'function5', 'lock2'),
('script4', 'function6', 'lock3')],
[('script2', 'function4', 'lock1'),
('script5', 'function7', 'lock3')],
[('script8', 'function10', 'lock1, lock2')]
]
So my output for this data is 3 groups, where each group has only 1 occurence of a particular 'lock', but if they have the same 'script' value then they can be put in the same group regardless of multiple occurences of the same 'lock'. Also the last data item 'script8' has 2 'locks' and so should be in a group that does not have an existing 'lock1' or 'lock2'.
It does not have to be in this format, I can use dictionary/set/tuples/list/whatever else. I found a way but it is not pretty, so was wondering if there was a short simple way of doing this grouping.
I tried (found from another solution)
groups = []
uniquekeys = []
data = sorted(tmis, key=lambda x: x[0] )
for k, g in itertools.groupby(data, lambda x: x[0]):
groups.append( list(g) )
uniquekeys.append(k)
but this groups only by the 'script' value. Any ideas?
EDIT: I guess my explanation was not very clear. What I am trying to do is group the tuples in such a way that no two 'scripts' with the same 'lock' are in the same group (UNLESS the 'script' is the same)
I can post my current (ugly) solution to this if it helps.
Upvotes: 2
Views: 133
Reputation: 24846
Here's my solution:
def getscript(group, lock):
"""
returns the script used by the given lock in the given group
or None if no script uses the given lock
"""
for script, function, locks in group:
if lock in locks.split(', '):
return script
return None
def compatible(group, task):
"""
tells if a task ((script, function, locks) tuple) can be added to a group
"""
for lock in task[2].split(', '):
script = getscript(group, lock)
if script and script != task[0]:
return False
return True
def makegroups(tasks):
groups = []
for task in tasks:
try:
group = next(grp for grp in groups if compatible(grp, task))
except StopIteration:
groups.append([task])
else:
group.append(task)
return groups
Upvotes: 0
Reputation: 11
Your example doesn't fit well with the description you gave. For example, you have s3,l2 and s4,l3 in the same group as s1,l1's.
Assuming you just wanted to do what you told in the text and not your desired output. Here is the code -
tmis = [
( 's1', 'm1', 'l1' ),
( 's1', 'm2', 'l1' ),
( 's1', 'm3', 'l1' ),
( 's2', 'm4', 'l1' ),
( 's1', 'm5', 'l2' ),
( 's4', 'm6', 'l3' ),
( 's5', 'm7', 'l3' ),
( 's8', 'm10', 'l1, l2' )
]
d={}
for i in tmis:
flag=0
if d.has_key(i[2]):
d[i[2]].append(i)
flag=1
else:
for key in d.keys():
if d[key][0][0] == i[0]:
d[key].append(i)
flag=1
break
if flag==0:
d[i[2]] = []
d[i[2]].append(i)
print d
Upvotes: 1