-4

I have a list of tuples:

l = [(x,y,2),(x,y,3),(x,y,4),(x,y,2),(x,y,2),(x,y,3)]

I need to extract tuples that share the last value into a list of lists of tuples:

nl = [[(x,y,2),(x,y,2),(x,y,2)],[(x,y,3),(x,y,3)]]

I don't know the last value of course.

dyb
  • 59
  • 8

3 Answers3

3

with modules

Using groupby from itertools you can group with a lambda by first sorting with that same lambda and then grouping. With a list comprehension you then group together all the groupings and filter out everything that is of length 1 to get rid of tuples that do not share values.

from itertools import groupby

tuples = [(1, 2, 2), (3, 1, 3), (1, 2, 4), (8, 9, 2), (12, 1, 2), (0, 1, 3)]

tuple_tail = lambda (first, mid, last): last

tuples.sort(key=tuple_tail)

print filter(lambda item: len(item) > 1, [list(group) for key, group in groupby(tuples, tuple_tail)])

without modules

So this one isn't the best solution but it's a solution. I defined some helper functions that

  1. retrieves last of tuple
  2. compares equality of two tuples.

Then wrote a custom group function that searches for all elements that are equal by using filter and then map that across all elements to obtain a list with all possible groupings (group all). I couldn't think of a way of using a list comprehension without making a mess so I went with reduce and wrote a function to remove elements that were duplicates and/or length of 1 (fn). This could surely be optimized if you used set or maybe just a different approach in general. Hope this helps you find whatever that approach will be.

tuples = [(1, 2, 2), (3, 1, 3), (1, 2, 4), (8, 9, 2), (12, 1, 2), (0, 1, 3)]
# helper functions
tuple_tail = lambda (first, mid, last): last
is_tuples_equal = lambda tuple1, tuple2: tuple_tail(
    tuple1) == tuple_tail(tuple2)

# groups by last (_,_,last)
group_by_last = lambda tuple: filter(
    lambda item: is_tuples_equal(item, tuple), tuples)

# get all groupings
group_all = map(group_by_last, tuples)

# if group is not in list and not length of 1 insert into list
fn = lambda acc, val: acc if val in acc or len(val) == 1 else acc + [val]

print reduce(fn, group_all, [])

with list comprehension

If you create a dictionary and use the tuple_tail values of each tuple as the key and make the value as the all the tuples that contain that key as their tail. You can then use a list comprehension to accumulate the values of the dictionary and dis include elements of length less than 1.

tuples = [(1, 2, 2), (3, 1, 3), (1, 2, 4), (8, 9, 2), (12, 1, 2), (0, 1, 3)]

mydict = dict()

create = lambda tupl: mydict.update({tuple_tail(tupl): [tupl]})
update = lambda tupl: mydict[tuple_tail(tupl)].append(tupl)
tuple_tail = lambda (first, mid, last): last

populate = lambda tupl: update(tupl) if tuple_tail(tupl) in mydict else create(tupl)
map(populate, tuples)

print [tuple for tuple in mydict.values() if len(tuple) > 1]

end results

[[(1, 2, 2), (8, 9, 2), (12, 1, 2)], [(3, 1, 3), (0, 1, 3)]]
Jonathan Portorreal
  • 2,730
  • 4
  • 21
  • 38
1

you can use dict to group the item with same last element

x,y= 'x','y'

l = [(x,y,2),(x,y,3),(x,y,4),(x,y,2),(x,y,2),(x,y,3)]
res = {}
for item in l:
  if item[2] not in res:
    res[item[2]] = []
  res[item[2]].append(list(item))

print filter( lambda x: len(x) > 1 , res.values())

[['x', 'y', 2], ['x', 'y', 2], ['x', 'y', 2]], [['x', 'y', 3], ['x', 'y', 3]]

or using pandas

l = pd.Series( [(x,y,2),(x,y,3),(x,y,4),(x,y,2),(x,y,2),(x,y,3) ])

print [ line[1].tolist() for line in l.groupby( lambda x: l[x][2] ) if len(line[1]) > 1]

[[('x', 'y', 2), ('x', 'y', 2), ('x', 'y', 2)], [('x', 'y', 3), ('x', 'y', 3)]]
galaxyan
  • 5,944
  • 2
  • 19
  • 43
0

First, sort according to last elements (You can use this one)

Then, group them. You can simply use a for loop. A pseudocode is:

cur_value = list[0][2] #second element of first tuple
llt = []; #list_of_list_of_tuples
for tuple in list:
     l_tpl = []
     if cur_value == tuple[2]:
         l_tpl.append(tuple)
     else:
         if len(l_tpl) > 1:
             llt.append(l_tpl)
if len(l_tpl) > 1:
     llt.append(l_tpl)  # we need to add the last list of tuples. 

I haven't tested and I'm not sure of the syntax.

Community
  • 1
  • 1
smttsp
  • 4,011
  • 3
  • 33
  • 62