排序列表中不会产生正确的结果
蟒蛇的问题在这里:排序列表中不会产生正确的结果
我运行一个排序功能按日期,一些数据进行排序,并得到不正确的输出。我准备了一些简短版本的代码,其中包含一些示例数据以显示错误(完整的代码无趣,完整的实际数据是专有的)。
下面是代码:
import operator
mylist = [['CustomerID_12345', 'TransactionID_1001', '12/31/2012'],
['CustomerID_12345', 'TransactionID_1002', '3/12/2013'],
['CustomerID_12345', 'TransactionID_1003', '1/7/2013'],
['CustomerID_12345', 'TransactionID_1004', '12/31/2012']]
sorted_list = sorted(mylist, key=operator.itemgetter(2))
print type(mylist)
print len(mylist)
for i in mylist:
print i
print "" # just for a line break for convenience
for i in sorted_list:
print i
并且输出是:
<type 'list'>
4
['CustomerID_12345', 'TransactionID_1001', '12/31/2012']
['CustomerID_12345', 'TransactionID_1002', '3/12/2013']
['CustomerID_12345', 'TransactionID_1003', '1/7/2013']
['CustomerID_12345', 'TransactionID_1004', '12/31/2012']
['CustomerID_12345', 'TransactionID_1003', '1/7/2013']
['CustomerID_12345', 'TransactionID_1001', '12/31/2012']
['CustomerID_12345', 'TransactionID_1004', '12/31/2012']
['CustomerID_12345', 'TransactionID_1002', '3/12/2013']
第一块是原始数据,并且第二个是输出。由于我试图按日期排序,很容易发现排序无法正常工作。
有人能帮助解释错误,并建议如何纠正呢? 感谢提前:)
这是因为Python将它们视为字符串而不是日期。
这是因为'1'小于'2'小于'3' 另外'/'小于数字,所以这是你的问题。
而是试图把它们的比较结果为日期,使用datetime
模块。
这里有一个例子:
from datetime import datetime
your_date = datetime.strptime('1/1/2013', "%m/%d/%Y")
my_date = datetime.strptime('12/3/2011', "%m/%d/%Y")
print your_date > my_date
[Out]: True
谢谢。由于我正在读取CSV文件中的原始数据,读取文件时转换它们的最佳方法是什么?非常感谢。 – Optimesh
@Optimesh,只需使用'datetime.strptime(mylist [i] [2],“%m /%d /%Y”)。date',其中i是0,1,2,3,...当场。如果我的回答很有帮助,你会介意接受吗?谢谢。 – sshashank124
自动导入csv数据的方式吗? – Optimesh
它的正确排序。您按照日期字段以不符合实际日期排序的愚蠢格式进行排序。如果使用标准的ISO格式(YYYY-MM-DD),它将按照您的预期排序。另外,如果你使用日期使用的python数据结构,例如从日期时间模块中,它将按照您的预期进行排序。
import datetime
mylist = [
['CustomerID_12345', 'TransactionID_1001', datetime.date(2012, 12, 13)],
['CustomerID_12345', 'TransactionID_1002', datetime.date(2013, 3, 12)],
...
]
或者,借用其他答案之一。如果您正在某处读取数据并希望将其从原始字符串格式转换为内部表示形式,这可以帮助您。
import datetime
mylist = [
['CustomerID_12345', 'TransactionID_1001',
datetime.datetime.strptime('12/31/2012', '%m/%d/%Y').date()],
['CustomerID_12345', 'TransactionID_1002',
datetime.datetime.strptime('3/12/2013', '%m/%d/%Y').date()],
...
]
另外,使用字符串只有...
mylist = [
['CustomerID_12345', 'TransactionID_1001', '2012-31-12'],
['CustomerID_12345', 'TransactionID_1002', '2013-03-12'],
...
]
如果你已经有像在你的问题一个数组,你可以很容易地将其转换:
new_list = [f1, f2, datetime.datetime.strptime(f3, '%m/%d/%Y').date()
for f1, f2, f3 in old_list]
只是一个M/D/YYYY(4/2/2014)格式是有史以来最愚蠢的日期格式之一,只有M/D/YY(4/2/14)比这更糟糕。
最好的格式按大小顺序排列,因为这是我们用于数字的方向。那些在使用正确的零填充的情况下,可以很容易地进行排序(2014-04-02),这就是为什么他们在计算机中找到自己的位置,尤其是文件名。没有那么好的格式按单位升序排列,并不尊重我们写下数字的方式,这个系统正在我国使用(今天是2014年2月4日)。但是混杂格式不能按照升序和降序排列单位,这是我们应该在几个世纪前杀死的。
感谢您的帮助。现在是2/4/14 :) 从CSV文件导入数据时,您是否知道更正此方法的方法? – Optimesh
第二个代码清单基本上告诉你如何做到这一点。你只需要用变量替换strptime的第一个参数。 –
为此添加了一个示例。 –
按日期排序:
from datetime import datetime
mylist = [['CustomerID_12345', 'TransactionID_1001', '12/31/2012'],
['CustomerID_12345', 'TransactionID_1002', '3/12/2013'],
['CustomerID_12345', 'TransactionID_1003', '1/7/2013'],
['CustomerID_12345', 'TransactionID_1004', '12/31/2012']]
sorted_list = sorted(mylist, key=lambda x: datetime.strptime(x[2],'%m/%d/%Y'))
for item in sorted_list:
print item
或者你可以存储日期日期时间摆在首位。如果他们是有充分理由的字符串,那么你可以先添加一个datetime列:
for item in mylist:
item.append(datetime.strptime(item[2], '%m/%d/%Y'))
sorted_list = sorted(mylist, key=lambda x: x[3])
for item in sorted_list: print item[:3]
这是一个正确的解决方案,所以我没有下调,但它也是一个糟糕的解决方案,因为它教会了非常不好的习惯,即使用错误的格式,然后将它随时翻译成一个好的习惯。 –
@perreal感谢您的帮助:) – Optimesh
它做正确,因为字符串以'“1''小于开始'串” 3''。同样''2'是''/''。 – metatoaster