简体   繁体   English

如何在python中对生成器类型进行排序

[英]How to sort generator type in python

My code has below lines 我的代码有以下几行

get_alarm_list = conn.query_alarms(query.filter_expr,
                                   query.orderb) 
print "type is:", type(get_alarm_list)
for alarm in get_alarm_list:
    if alarm.severity == 'critical':
        alarm.severity = 2
    elif alarm.severity == 'moderate':
        alarm.severity = 1
    else:
        alarm.severity = 0

alarm_list = sorted(get_alarm_list),
                    key=lambda a: a.severity,
                    reverse=True)
return [alarms.Alarm.from_db_model(alarm)
        for alarm in alarm_list]

Output: 输出:

type is <type 'generator'>

The objects in the list are: 列表中的对象是:

for alarm in get_alarm_list:
     print alarm

Output:
<aodh.storage.models.Alarm object at 0x7fa4c0cb1c50>
<aodh.storage.models.Alarm object at 0x7fa4c0cb17d0>
<aodh.storage.models.Alarm object at 0x7fa4c0d86f10>
<aodh.storage.models.Alarm object at 0x7fa4ca372110>
<aodh.storage.models.Alarm object at 0x7fa4ca372190>
<aodh.storage.models.Alarm object at 0x7fa4c0c55d90>

And each alarm consists of the below data 并且每个警报包含以下数据

 {'alarm_actions': [u'log://'], 'ok_actions': [], 'description': u'instance running hot', 'state': u'insufficient data', 'fields': ['alarm_actions', 'ok_actions', 'severity', 'timestamp', 'description', 'time_constraints', 'enabled', 'state_timestamp', 'rule', 'alarm_id', 'state', 'insufficient_data_actions', 'repeat_actions', 'user_id', 'project_id', 'type', 'name'], 'repeat_actions': False, 'enabled': True, 'state_timestamp': datetime.datetime(2016, 5, 27, 6, 41, 5, 987428), 'rule': {u'meter_name': u'cpu_util', u'evaluation_periods': 3, u'period': 600, u'statistic': u'avg', u'threshold': 70.0, u'query': [], u'comparison_operator': u'gt', u'exclude_outliers': False}, 'name': u'ddd', 'alarm_id': u'f5045ed5-5c53-4a6e-be53-23d3368f40c6', 'time_constraints': [], 'insufficient_data_actions': [], 'timestamp': datetime.datetime(2016, 5, 27, 6, 41, 5, 987428), 'user_id': u'9a65b258b5a24e74ac5feae2f6c54229', 'project_id': u'28d1c27e782c4448bf53da00f49d3e1b', 'type': u'threshold', 'severity': 2}

How can i iterate over the generator? 我如何迭代生成器?

alarm_list = sorted(get_alarm_list,
                    key=lambda a: a.severity,
                    reverse=True)

But here alarm_list is empty. 但是这里alarm_list为空。 How can i use sort function on generator get_alarm_list 如何在生成器get_alarm_list上使用排序功能

The problem in your code is that you are trying to sort exhausted generator ( you sorting after for loop thought generator). 在你的代码的问题是,你正在试图理清疲惫发生器(您整理后for循环发电机思想)。 You can sort result produced by generator object, so the option for you is to exhaust generator into variable in other words to create new list based on get_alarm_list as list(generator) and then iterate and sort it with simple sorted function or list.sort method: 您可以对生成器对象产生的结果进行排序,因此您的选择是将生成器耗尽为变量,换句话说,基于get_alarm_list作为list(generator)创建新列表,然后使用简单的排序函数或list.sort方法对其进行迭代和排序:

get_alarm_list = conn.query_alarms(query.filter_expr, query.orderb) 
sorted_alarm_list = sorted(list(get_alarm_list),
                               key=lambda a: a.severity,
                               reverse=True)
for alarm in sorted_alarm_list:
    print alarm

Note 1 : After execution of list(get_alarm_list) - get_alarm_list generator became empty. 注意1 :执行list(get_alarm_list) get_alarm_list生成器为空。 And the only item which store result of conn.query_alarms is the sorted_get_alarm_list . 并且存储conn.query_alarms结果的唯一项目是sorted_get_alarm_list You can read more about generators on Generators Python Wiki and Understanding Generators in Python 您可以在Generators Python Wiki上 了解有关Generators的更多信息,在Python中了解Generators

Note 2 : Actually you can pass generator object to sorted and you will get same list as passing list(generator) , however sorted works faster if you pass a list to it ( see more on SO answer sorted() using Generator Expressions Rather Than Lists ). 注2 :实际上,您可以传递生成器对象进行sorted并且将得到与传递list(generator)相同的列表,但是如果将列表传递给它,则sorted工作得更快(有关更多信息,请参见使用生成器表达式而不是列表的生成器表达式sorted()) )。

The problem you're running into is that you're consuming the whole generator in your for loop when you modify the severity attributes of your objects. 您遇到的问题是,修改对象的severity属性时,您在for循环中消耗了整个生成器。 That means there's nothing left to iterate on when you call sorted , since generators are good for one use only. 这意味着在调用sorted ,无需进行任何迭代,因为生成器仅适合一种用途。

You can fix this by getting rid of the first loop, and putting the severity-transforming logic into the key lambda function: 您可以通过摆脱第一个循环并将严重性转换逻辑放入key lambda函数中来解决此问题:

alarms_gen = conn.query_alarms(query.filter_expr, query.orderb) 
alarms_list = sorted(alarms_gen,
                     key=lambda x: {'critical': -2, 'moderate': -1}.get(x.severity, 0))

Note that I've renamed your get_alarms_list variable to be less misleading (it's not a list). 请注意,我已将您的get_alarms_list变量重命名为具有较小的误导性(这不是列表)。 I've also made it so that reverse=True is not needed in the sorted call by mapping the higher priorities to negative key values. 我也做到了,通过将较高优先级映射到负键值,在排序调用中不需要reverse=True

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM