Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

selective printing from a list

Tags:

python

Say for an example, I've a list like this:

q_list = [('94.vmtest2', 'sgmops', 'Andy Hays', '27/04 00:27:26', 'C', '27/04 00:28:31', 'vmtest1.hep', 'express', '00:00:10', '00:01:04'), 
          ('96.vmtest2', 'sgmops', 'John Dee', '27/04 01:27:26', 'C', '27/04 01:28:33', 'vmtest1.hep', 'short', '00:00:09', '00:01:06'),
          ('99.vmtest2', 'sgmops', 'Andy Hays', '27/04 07:19:56', 'C', '27/04 07:21:12', 'vmtest1.hep', 'express', '00:00:10', '00:01:14'), 
          ('103.vmtest2', 'sgmops', 'John Dee', '27/04 14:08:00', 'C', '27/04 14:09:16', 'vmtest1.hep', 'express', '00:00:10', '00:01:16'),
          ('102.vmtest2', 'sgmops', 'John Dee', '27/04 14:02:38', 'C', '27/04 14:10:12', 'vmtest1.hep', 'short', '00:00:10', '00:01:10')]

which is formed from the log files. and then I have a dictionary like this:

q_dict = {'username': 'johndee', 'queue': 'short'}

which is formed from a query string (the user input). What I want is to print [first 8 items of] the only lines from the list match with the value in the dictionary. In this case, I'll only print these two lines:

96.vmtest2   sgmops  John Dee  27/04 01:27:26  C  27/04 01:28:33  vmtest1.hep  short
102.vmtest2  sgmops  John Dee  27/04 14:02:38  C  27/04 14:10:12  vmtest1.hep  short

In fact it doesn't have to be a dictionary at all; the user input (command-line argument) is like this:

'formatDate(%m/%d) == 4/27 && username == John Dee && queue == short'

and I'm creating the dictionary out of that. Any idea how can I do that? Thanks in advance for any help. Cheers!!

like image 878
MacUsers Avatar asked Mar 18 '26 10:03

MacUsers


2 Answers

Firstly, I would suggest that you store your data in namedtuples or a custom class, instead of just raw tuples. This way you can access the attributes by name (e.g. by using operator.attrgetter). The other option is to use a dict.

Then, you can simply do the following (assuming your items are dicts):

[item for item in q_list if all((item[attr] == q_dict[attr]) 
                                 for q_dict in filters)]

This of course only works if your conditions always follow the pattern shown in your question (no ||, no != or stuff like that).

If you can only use tuples, then you can create a dictionary that maps the names of attributes to tuples-indices.

Now, when you print them, you can just create a list of attributes that should be printed, and use it like this:

for item in filtered_items:
    print "\t".join(item[attr] for attr in attributes_to_print) + "\n"
like image 90
Björn Pollex Avatar answered Mar 20 '26 01:03

Björn Pollex


The most common approach is to use a list comprehension, for instance to filter by username:

[x for x in q_list if x[2] == 'John Dee']

You can also use filter:

filter(lambda x: x[2] == 'John Dee', q_list)

You can thus use your q_dict to filter by user and/or queue easily.

[x for x in q_list if [x[2].lower().replace(' ', ''), x[7]] == q_dict.values()]

As suggested in Space_C0wb0y's answer, using namedtuple would be a good approach, you can map out the fields rather easily:

fields =  ['field1', 'field2', 'username', 'field4', 'field5', 'field6', 'field7', 'queue', 'field9', 'field10']
Item = namedtuple('Item', fields)

For the sake of the argument, let's convert the tuples in your list to namedtuples:

q_namedtuple = [Item(*x) for x in q_list]

And then you can filter dynamically based on the query params. For instance to get a list of items where all query params match the given fields:

[item for item in q_namedtuple if all(getattr(item, k) == v for k, v in q_dict.iteritems())]

That is assuming the username in q_dict actually matched the field for username...it doesn't in your example but you can work around that. Similarly you could create a list of dicts, that'd make working with your list a bit easier:

q_list_of_dicts = [dict(zip(fields, x)) for x in q_list]

Which would give you a list of dicts like:

{'field1': '102.vmtest2',
 ...etc
 'queue': 'short',
 'username': 'John Dee'}

Then you can filter similarly:

[item for item in q_list_of_dicts if all(item.get(k) == v for k, v in q_dict.iteritems())]

Personally I think I prefer the dict approach. Whole things rolled up using for loops instead (and one generator expression):

results = []
for item in q_list:
    d = dict(zip(fields, item))
    # use some other logic to filter
    if all(d.get(k) == v for k, v in q_dict.iteritems()):
         results.append(d)
like image 31
zeekay Avatar answered Mar 19 '26 23:03

zeekay



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!