0

I have a list of tuples that consist of objects of a certain class and differ in their dimension:

my_list = [(obj1, obj2), (obj3, obj1), (obj4, obj1), (obj2,),...]

All of these objects have an attribute label which is of type string and holds an object label e.g. 'object_1', 'object_2' and so on.

Now I want to extract the string representation of the tuples holding the attribute values (labels) e.g.:

my_new_list = ['(object_1, object_2)', '(object_3, object_1)', '(object_4, object_1)', '(object_2,)', ...]

I have looked up how to extract a list of attributes from a list of objects and how to convert a tuple to string and would probably achieve my goal with some nested for loops. But I got stuck in some messy code here..

But isn't there some nice pythonic way to do this?

Thanks in advance!

*EDIT: Some of the tuples are one dimensional e.g. (obj2,). Sorry, I forgot that and now have adapted my question!

5
  • What's wrong with a standard list comprehension here? Commented Sep 19, 2017 at 9:10
  • It's not the objects only but the attributes within the string representation of the tuples. Commented Sep 19, 2017 at 9:17
  • As a general tip you can usually see the structure of the comprehension just by writing it out with actual for loops. In this case you'd write for obj1, obj2 in my_list to bring out the tuples, and then append '(%s,%s)' % (obj1.label, obj2.label) to an initially empty list. And you can see that same structure in the answers below. Edit: Just saw the edit. Same general principle applies. Commented Sep 19, 2017 at 9:21
  • Thanks anyway for your tip! Commented Sep 19, 2017 at 9:27
  • I added a more general answer not using nested comprehensions that I think reads nicely and is standard python. It's a great practice to give your classes good string representations with a __repr__ function so they can be used in a manner like this. print(my_obj) is just nicer than print(my_obj.label) if the label makes sense to be the...well...label of the object. Commented Sep 19, 2017 at 9:53

5 Answers 5

3

You can do

["(%s, %s)" %(i.label, j.label) for i, j in my_list]

If dynamic length inside tuple:

["(%s)" %", ".join([j.label for j in i]) for i in my_list]
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your answer. This is a really nice solution. Unfortunately, I forgot one detail: The tuples are sometimes of dimension one e.g. (obj1,). I will adapt my question. Sorry!
@CordKaldemeyer Edited the answer
Works like a charm! You saved my day. Thanks!
1

The two other simple list comprehension answers work fine for an arbitrary list of tuples of objects with the attribute. However, Python has some great built-in functionality which let you choose the string representation of your objects, and most built-in types have this already. For example, any tuple can be cast to it's string representation just by encasing the tuple with str(tuple):

>>> str((5, 4))
'(5, 4)'

Now, if you did this with a tuple of arbitrary objects, then you'd get a string which has the actual object handle like <__main__.YourClass object at 0x10ad58fd0> which is ugly. But, if you provide a __repr__ function inside your class definition, then you can change that standard handle to something you like instead. In this case, your label seems like a good candidate to return for the string representation of your object. Here's a minimal example created with your same code:

class LabeledObj:

    def __init__(self, label):
        self.label = label

    def __repr__(self):
        return self.label


obj1 = LabeledObj('object_1')
obj2 = LabeledObj('object_2')
obj3 = LabeledObj('object_3')
obj4 = LabeledObj('object_4')

my_list = [(obj1, obj2), (obj3, obj1), (obj4, obj1), (obj2,)]

my_new_list = [str(obj_tuple) for obj_tuple in my_list]
print(my_new_list)

['(object_1, object_2)', '(object_3, object_1)', '(object_4, object_1)', '(object_2,)']

Now I think this is very pythonic and very clear later in the code, and defining the __repr__ only takes an additional two lines of code. And now you can print(my_obj) instead of print(my_obj.label) which reads nicely.

1 Comment

I guess this is the cleanest solution. Thanks to all of you!
1

You can use list comprehension for that:

['({}, {})'.format(el1.label, el2.label) for el1, el2 in my_list]

To not depend from tuple dimension use helper function:

def tuple_print(tup):
    return '({})'.format(', '.join(t.label for t in tup))

my_new_list = [tuple_print(tup) for tup in my_list]

2 Comments

Thanks for your answer which looks nice as well. Unfortunately, I have forgotten to mention that the tuples differ in their dimension..
Edit my answer. Note that I use python3
1

Tuple list elements count using len() + generator expression

temp = list((int(j) for i in test_list for j in i)) 
res = len(temp)

Comments

0

You can use map function to help. This can be complete in one line of code

my_new_list = list(map(lambda P: '({})'.format(','.join(list(map(lambda t:t.label,list(P))))),my_list))

This also work with one dimension tuples.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.