Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter a tuple with another tuple in Python

I have a list of tuples that is created with the zip function. zip is bringing together four lists: narrative, subject, activity, and filer, each of which is just a list of 0s and 1s. Let's say those four lists look like this:

narrative = [0, 0, 0, 0]
subject = [1, 1, 0, 1]
activity = [0, 0, 0, 1]
filer = [0, 1, 1, 0]

Now, I'm ziping them together to get a list of boolean values indicating if any of them are True.

ny_nexus = [True if sum(x) > 0 else False for x in zip(narrative, subject, activity, filer)]

The problem I'm having now, is getting a second list of tuples for which the names of the variables is returned if it had a 1 during the iteration. I imagine it would look something like this:

variables = ("narrative", "subject", "activity", "filer")
reason = [", ".join([some code to filter a tuple]) for x in zip(narrative, subject, activity, filer)]

I just can't figure out how I'd go about this. My desired output would look like this:

reason
# ["subject", "subject, filer", "filer", "subject, activity"]

I'm somewhat new to Python, so I apologize if the solution is easy.

like image 246
tblznbits Avatar asked Sep 26 '22 07:09

tblznbits


1 Answers

Store tuples in a dictionary for a cleaner solution:

tups = {'narrative': narrative,
        'subject': subject,
        'activity': activity,
        'filer': filer}

The solution:

reason = [', '.join(k for k, b in zip(tups, x) if b) for x in zip(*tups.values())]

It can also be written using itertools.compress:

from itertools import compress
reason = [', '.join(compress(tups, x)) for x in zip(*tups.values())]

Solutions above do not preserve the order of tuples, e.g. they can return something like

['subject', 'filer, subject', 'filer', 'activity, subject']

If you need the order to be preserved, use collections.OrderedDict as shown below:

from collections import OrderedDict

tups = OrderedDict([
    ('narrative', narrative),
    ('subject', subject),
    ('activity', activity),
    ('filer', filer)
])

# The result is ['subject', 'subject, filer', 'filer', 'subject, activity']

EDIT: The solution that doesn't involve dictionaries:

from itertools import compress
reason = [', '.join(compress(variables, x))
          for x in zip(narrative, subject, activity, filer)]

Consider using dictionaries if the zip(...) call no longer fits on one line.

like image 129
vaultah Avatar answered Sep 28 '22 05:09

vaultah