从列表中选择性打印

时间:2011-05-22 14:54:28

标签: python

举个例子,我有一个这样的列表:

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')]

由日志文件组成。然后我有一个这样的字典:

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

由查询字符串(用户输入)组成。我想要的是打印[前8项]列表中唯一的行与字典中的值匹配。在这种情况下,我只打印这两行:

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

事实上,它根本不是一本字典;用户输入(命令行参数)是这样的:

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

我正在创建字典。知道我该怎么办?在此先感谢您的帮助。干杯!!

4 个答案:

答案 0 :(得分:2)

首先,我建议您将数据存储在namedtuple s或自定义类中,而不仅仅是原始元组。这样您就可以按名称访问属性(例如,使用operator.attrgetter)。另一种选择是使用dict

然后,您可以简单地执行以下操作(假设您的项目为dict s):

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

这当然只有在您的条件始终遵循问题中显示的模式(没有||,没有!=或类似的东西)时才有效。

如果你只能使用元组,那么你可以创建一个字典,将属性的名称映射到元组索引。

现在,当你打印它们时,你可以创建一个应该打印的属性列表,并像这样使用它:

for item in filtered_items:
    print "\t".join(item[attr] for attr in attributes_to_print) + "\n"

答案 1 :(得分:1)

最常见的方法是使用list comprehension,例如按用户名过滤:

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

您还可以使用filter

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

您可以使用q_dict轻松按用户和/或队列进行过滤。

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

根据Space_C0wb0y's answer的建议,使用namedtuple是一种很好的方法,您可以轻松地绘制字段:

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

为了论证,让我们将列表中的元组转换为namedtuples:

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

然后您可以根据查询参数动态过滤。例如,获取所有查询参数与给定字段匹配的项目列表:

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

假设q_dict中的用户名实际上与用户名字段匹配...它不在您的示例中,但您可以解决此问题。同样,您可以创建一个dicts列表,这样可以更轻松地处理您的列表:

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

这会给你一个像:

这样的词汇表
{'field1': '102.vmtest2',
 ...etc
 'queue': 'short',
 'username': 'John Dee'}

然后你可以类似地过滤:

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

我个人认为我更喜欢dict方法。整个事情使用for循环(和一个生成器表达式)汇总:

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)

答案 2 :(得分:1)

对于formatDate,它可能更复杂,但为了简单相等,您可以使用eval:

test_string = "username == 'John Dee' && queue == 'short'"

for a, b, username, formatDate, d, e, f, queue, g, h in q_list:
    if eval(test_string.replace('&&', 'and')):
        print '%s: %s' % (username, queue)

你可以通过替换'||'来制作'或'语句这是相当动态的

不要忘记将值放在引号中(不是queue == short而是queue == 'short'

给定q_list上的结果是:

John Dee: short
John Dee: short

答案 3 :(得分:0)

一旦您针对过滤条件解析了用户输入,请检查每个条件的每个条目,将一组索引保存到q_list中以匹配每个条件,然后执行集合交集以查找与所有条件匹配的索引

in pseudo-ish code:

n = len(q_list)
accepted = set(range(n))
for condition in conditions:
  accepted = accepted.intersection({i for i in range(n) if condition_holds(q_list(i), condition)})

result = [q_list[i] for i in accepted]