举个例子,我有一个这样的列表:
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'
我正在创建字典。知道我该怎么办?在此先感谢您的帮助。干杯!!
答案 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]