Python 如何在datetime上对类进行排序,对集合进行排序.deque
在如何实现getitem、iter方法或生成器函数对我创建的类和类容器进行排序方面,我确实需要一些帮助 我创建了一个具有send_time(datetime)和period_length(int)属性的报表类。 我还为报表创建了一个ReportDeque容器,它继承自collections.deque 我需要向类及其容器添加排序功能 到目前为止,我已经对工作进行了排序,但希望得到list.sort()样式的工作Python 如何在datetime上对类进行排序,对集合进行排序.deque,python,unit-testing,sorting,python-2.7,comparison,Python,Unit Testing,Sorting,Python 2.7,Comparison,在如何实现getitem、iter方法或生成器函数对我创建的类和类容器进行排序方面,我确实需要一些帮助 我创建了一个具有send_time(datetime)和period_length(int)属性的报表类。 我还为报表创建了一个ReportDeque容器,它继承自collections.deque 我需要向类及其容器添加排序功能 到目前为止,我已经对工作进行了排序,但希望得到list.sort()样式的工作 sortedList = sorted(list, key=lambda rep
sortedList = sorted(list, key=lambda report: report.send_time)
sortedDeque = sorted(deque, key=lambda report: report.send_time)
我正在努力实现Report中的getitem,以及ReportDeque中的iter,next方法。我只是找不到我需要的例子来让这一切正常运作
也许应该使用生成器函数对collections.deque容器进行排序。
如果有多种生成器以不同的方式对deque进行排序,那就太好了
下面是我的测试用例。要在以下代码中运行unittest,请键入:
python -m unittest test_reports
输出在这篇文章的末尾
先谢谢你
-------------------test_reports.py snip--------------------------
#!/usr/bin/env python
from datetime import datetime
from collections import deque
import unittest
import inspect
class Report(object):
"""
Contains all information contained in a report
"""
def __init__(self, periodStart, periodEnd, sendTime):
self.period_start = periodStart
self.period_end = periodEnd
self.send_time = sendTime
self.send_timestamp = (sendTime - datetime(1970, 1, 1)).total_seconds()
self.period_length = (periodEnd - periodStart).total_seconds()
#def __getitem__(self, key):
class ReportDeque(deque):
"""
Container for processing, sorting Report objects
"""
#def __iter__(self)
#def next(self)
class TestReports(unittest.TestCase):
def setUp(self):
self.list = []
self.deque = ReportDeque()
# send_time 12/4/13, day length report
report = Report(datetime(2013, 12, 3, 0), datetime(2013, 12, 3, 23), datetime(2013, 12, 4, 0))
self.list.append(report)
self.deque.append(report)
# send_time 12/3/13, day length report
report = Report(datetime(2013, 12, 2, 0), datetime(2013, 12, 2, 23), datetime(2013, 12, 3, 0))
self.list.append(report)
self.deque.append(report)
# send_time 12/2/13, day length report
report = Report(datetime(2013, 12, 1, 0), datetime(2013, 12, 1, 23), datetime(2013, 12, 2, 0))
self.list.append(report)
self.deque.append(report)
# sorted with key function works
self.sortedList = sorted(self.list, key=lambda report: report.send_time)
self.sortedDeque = sorted(self.deque, key=lambda report: report.send_time)
def test_sort_deque_send_time(self):
self.print_inspect()
# deque does not have sort method. How to sort it?
self.deque.sort()
firstReport = self.deque[0]
print "send_time {} period_length {}".format(firstReport.send_time, firstReport.period_length)
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
def test_sort_list_send_time(self):
self.print_inspect()
# list.sort() not working. How to implement __get_item___?
self.list.sort()
firstReport = self.list[0]
print "send_time {} period_length {}".format(firstReport.send_time, firstReport.period_length)
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
def test_sorted_deque_send_time(self):
self.print_inspect()
firstReport = self.sortedDeque[0]
print "send_time {} period_length {}".format(firstReport.send_time, firstReport.period_length)
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
def test_sorted_list_send_time(self):
self.print_inspect()
firstReport = self.sortedList[0]
print "send_time {} period_length {}".format(firstReport.send_time, firstReport.period_length)
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
def print_inspect(self):
calling_function = inspect.stack()[1][3]
print "\nin {}()".format(calling_function)
if __name__ == "__main__":
unittest.main()
$ python -m unittest test_reports
in test_sort_deque_send_time()
E
in test_sort_list_send_time()
send_time 2013-12-04 00:00:00 period_length 82800.0
F
in test_sorted_deque_send_time()
send_time 2013-12-02 00:00:00 period_length 82800.0
.
in test_sorted_list_send_time()
send_time 2013-12-02 00:00:00 period_length 82800.0
.
======================================================================
ERROR: test_sort_deque_send_time (test_reports.TestReports)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_reports.py", line 51, in test_sort_deque_send_time
self.deque.sort()
AttributeError: 'ReportsDeque' object has no attribute 'sort'
======================================================================
FAIL: test_sort_list_send_time (test_reports.TestReports)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_reports.py", line 62, in test_sort_list_send_time
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
AssertionError: datetime.datetime(2013, 12, 4, 0, 0) != datetime.datetime(2013, 12, 2, 0, 0)
----------------------------------------------------------------------
Ran 4 tests in 0.011s
FAILED (failures=1, errors=1)
-------------------test_reports.py snip--------------------------
#!/usr/bin/env python
from datetime import datetime
from collections import deque
import unittest
import inspect
class Report(object):
"""
Contains all information contained in a report
"""
def __init__(self, periodStart, periodEnd, sendTime):
self.period_start = periodStart
self.period_end = periodEnd
self.send_time = sendTime
self.send_timestamp = (sendTime - datetime(1970, 1, 1)).total_seconds()
self.period_length = (periodEnd - periodStart).total_seconds()
#def __getitem__(self, key):
class ReportDeque(deque):
"""
Container for processing, sorting Report objects
"""
#def __iter__(self)
#def next(self)
class TestReports(unittest.TestCase):
def setUp(self):
self.list = []
self.deque = ReportDeque()
# send_time 12/4/13, day length report
report = Report(datetime(2013, 12, 3, 0), datetime(2013, 12, 3, 23), datetime(2013, 12, 4, 0))
self.list.append(report)
self.deque.append(report)
# send_time 12/3/13, day length report
report = Report(datetime(2013, 12, 2, 0), datetime(2013, 12, 2, 23), datetime(2013, 12, 3, 0))
self.list.append(report)
self.deque.append(report)
# send_time 12/2/13, day length report
report = Report(datetime(2013, 12, 1, 0), datetime(2013, 12, 1, 23), datetime(2013, 12, 2, 0))
self.list.append(report)
self.deque.append(report)
# sorted with key function works
self.sortedList = sorted(self.list, key=lambda report: report.send_time)
self.sortedDeque = sorted(self.deque, key=lambda report: report.send_time)
def test_sort_deque_send_time(self):
self.print_inspect()
# deque does not have sort method. How to sort it?
self.deque.sort()
firstReport = self.deque[0]
print "send_time {} period_length {}".format(firstReport.send_time, firstReport.period_length)
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
def test_sort_list_send_time(self):
self.print_inspect()
# list.sort() not working. How to implement __get_item___?
self.list.sort()
firstReport = self.list[0]
print "send_time {} period_length {}".format(firstReport.send_time, firstReport.period_length)
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
def test_sorted_deque_send_time(self):
self.print_inspect()
firstReport = self.sortedDeque[0]
print "send_time {} period_length {}".format(firstReport.send_time, firstReport.period_length)
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
def test_sorted_list_send_time(self):
self.print_inspect()
firstReport = self.sortedList[0]
print "send_time {} period_length {}".format(firstReport.send_time, firstReport.period_length)
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
def print_inspect(self):
calling_function = inspect.stack()[1][3]
print "\nin {}()".format(calling_function)
if __name__ == "__main__":
unittest.main()
$ python -m unittest test_reports
in test_sort_deque_send_time()
E
in test_sort_list_send_time()
send_time 2013-12-04 00:00:00 period_length 82800.0
F
in test_sorted_deque_send_time()
send_time 2013-12-02 00:00:00 period_length 82800.0
.
in test_sorted_list_send_time()
send_time 2013-12-02 00:00:00 period_length 82800.0
.
======================================================================
ERROR: test_sort_deque_send_time (test_reports.TestReports)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_reports.py", line 51, in test_sort_deque_send_time
self.deque.sort()
AttributeError: 'ReportsDeque' object has no attribute 'sort'
======================================================================
FAIL: test_sort_list_send_time (test_reports.TestReports)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_reports.py", line 62, in test_sort_list_send_time
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
AssertionError: datetime.datetime(2013, 12, 4, 0, 0) != datetime.datetime(2013, 12, 2, 0, 0)
----------------------------------------------------------------------
Ran 4 tests in 0.011s
FAILED (failures=1, errors=1)
首先,您需要使报表对象具有可比性,以便无需显式键即可排序。您可能应该仔细阅读丰富的比较,但是
\uu\cmp\uuu
可以做到这一点
class Report(object):
"""
Contains all information contained in a report
"""
def __init__(self, periodStart, periodEnd, sendTime):
self.period_start = periodStart
self.period_end = periodEnd
self.send_time = sendTime
self.send_timestamp = (sendTime - datetime(1970, 1, 1)).total_seconds()
self.period_length = (periodEnd - periodStart).total_seconds()
def __cmp__(self, other):
return cmp(self.send_time, other.send_time)
在测试list.sort()
时,这就是让测试通过所需的全部内容。对sorted(list)
和sorted(deque)
的测试也应该有效,但有一个问题。由于您正在请求有关\uu getitem\uuu
实现的帮助,我认为您认为sorted()
正在进行排序,并且也会对您的数据进行排序。这不是它的工作原理sorted(iterable)
将返回一个包含iterable项的新排序列表
如果你真的想在适当的位置对数据进行排序,你必须在deque.sort()
方法中实现一个deque排序算法才能在适当的位置进行排序,我不知道哪种算法对数据进行排序更有效(我甚至不确定这样做是否有意义),但我认为重建deque并利用python非常高效的排序算法可能更容易:
class ReportDeque(deque):
"""
Container for processing, sorting Report objects
"""
def sort(self, *args, **kwargs):
items = [self.pop() for x in xrange(len(self))]
items.sort(*args, **kwargs)
self.extend(items)
这会让你所有的考试都通过
更新
如果您希望在发送时间相等时使用周期长度
来消除歧义,只需将其添加到\uuuuuu cmp\uuuu
,如下所示:
def __cmp__(self, other):
cmp((self.send_time, self.period_length),
(other.send_time, other.period_length))
它是
ReportsDeque
还是ReportDeque
?我最初将报告集合命名为ReportsDeque(复数),但不断错误地反复输入ReportDeque(单数),因此在代码示例中我将其重命名为ReportDeque(singlular)。有语法错误吗?复数可能是一个更好的名称。强制代码golf:def sort(self,*args,**kwargs):self.extend(sorted(self.pop()表示x范围内的x(len(self)),*args,**kwargs))
。这是我的第一次实施。:)谢谢你,佩德罗和金达尔。刚吃过午饭回来,我就要开始工作了。定义cmp是有意义的。我盯着getitem和iter想“见鬼!”我知道sorted()返回list,这段代码很好地工作sorteddque=sorted(deque,key=lambda report:report.send_time)
可能是对deque的有效排序。deque.sort()算法的答案非常受欢迎,因为我最终希望实现ReportDeque sort(),并在第一次发送时间(从最早到最新),然后(当发送时间相等时)周期长度(从最小到最大)上进行排序。@Bradsurtevant使用\uu cmp\uuuuuu
,sorted(deque)也可以工作,没有关键参数。您提到的辅助排序条件也是\uuuu cmp\uuu
的一部分,它与deque.sort()无关。我将编辑答案以添加该选项。我真的怀疑任何可以实现的deque sort()算法是否会比python的内置list.sort()更好,即使是以重建deque为代价。@Pedro再次感谢您,“检查”了您的答案