根据特定字段

时间:2016-07-15 05:57:44

标签: python list python-2.7 sorting

概述:我有类似这样的数据(每行都是一个字符串):

  

81:0A:D7:19:25:7B, 2016-07-14 14:29:13 ,2016-07-14 14:29:15,-69,22:22 :22:22:22:23,空,^ M   3B:3F:B9:0A:83:E6, 2016-07-14 01:28:59 ,2016-07-14 01:29:01,-36,33:33:33: 33:33:31,空,^ M   B3:C0:6E:77:E5:31, 2016-07-14 08:26:45 ,2016-07-14 08:26:47,-65,33:33:33: 33:33:32,空,^ M   61:01:55:16:B5:52, 2016-07-14 06:25:32 ,2016-07-14 06:25:34,-56,33:33:33: 33:33:33,空,^ M

我想根据每个String中存在的第一个时间戳对每一行进行排序,对于这四个记录是:

  

2016-07-14 01:28:59

     

2016-07-14 06:25:32

     

2016-07-14 08:26:45

     

2016-07-14 14:29:13

现在我知道了sort()方法,但是我不明白如何在这里根据这个(时间戳)数量对所有行进行排序,我确实需要保持最终的排序数据相同格式,因为其他一些服务将使用它。

我也理解我可以制作key(),但我不清楚如何对时间戳字段进行排序。

3 个答案:

答案 0 :(得分:10)

您可以使用就地排序的列表方法list.sort或使用返回新列表的sorted()内置函数。 key参数采用一个函数,它在排序之前应用于序列的每个元素。您可以使用string.split(',')和索引到第二个元素的组合,例如some_list [1],所以:

In [8]: list_of_strings
Out[8]: 
['81:0A:D7:19:25:7B, 2016-07-14 14:29:13, 2016-07-14 14:29:15, -69, 22:22:22:22:22:23,null,^M',
 '3B:3F:B9:0A:83:E6, 2016-07-14 01:28:59, 2016-07-14 01:29:01, -36, 33:33:33:33:33:31,null,^M',
 'B3:C0:6E:77:E5:31, 2016-07-14 08:26:45, 2016-07-14 08:26:47, -65, 33:33:33:33:33:32,null,^M',
 '61:01:55:16:B5:52, 2016-07-14 06:25:32, 2016-07-14 06:25:34, -56, 33:33:33:33:33:33,null,^M']

In [9]: sorted(list_of_strings, key=lambda s: s.split(',')[1])
Out[9]: 
['3B:3F:B9:0A:83:E6, 2016-07-14 01:28:59, 2016-07-14 01:29:01, -36, 33:33:33:33:33:31,null,^M',
 '61:01:55:16:B5:52, 2016-07-14 06:25:32, 2016-07-14 06:25:34, -56, 33:33:33:33:33:33,null,^M',
 'B3:C0:6E:77:E5:31, 2016-07-14 08:26:45, 2016-07-14 08:26:47, -65, 33:33:33:33:33:32,null,^M',
 '81:0A:D7:19:25:7B, 2016-07-14 14:29:13, 2016-07-14 14:29:15, -69, 22:22:22:22:22:23,null,^M']

或者,如果您更愿意对列表进行排序,

list_of_strings
Out[12]: 
['81:0A:D7:19:25:7B, 2016-07-14 14:29:13, 2016-07-14 14:29:15, -69, 22:22:22:22:22:23,null,^M',
 '3B:3F:B9:0A:83:E6, 2016-07-14 01:28:59, 2016-07-14 01:29:01, -36, 33:33:33:33:33:31,null,^M',
 'B3:C0:6E:77:E5:31, 2016-07-14 08:26:45, 2016-07-14 08:26:47, -65, 33:33:33:33:33:32,null,^M',
 '61:01:55:16:B5:52, 2016-07-14 06:25:32, 2016-07-14 06:25:34, -56, 33:33:33:33:33:33,null,^M']

list_of_strings.sort(key=lambda s: s.split(',')[1])

list_of_strings
Out[14]: 
['3B:3F:B9:0A:83:E6, 2016-07-14 01:28:59, 2016-07-14 01:29:01, -36, 33:33:33:33:33:31,null,^M',
 '61:01:55:16:B5:52, 2016-07-14 06:25:32, 2016-07-14 06:25:34, -56, 33:33:33:33:33:33,null,^M',
 'B3:C0:6E:77:E5:31, 2016-07-14 08:26:45, 2016-07-14 08:26:47, -65, 33:33:33:33:33:32,null,^M',
 '81:0A:D7:19:25:7B, 2016-07-14 14:29:13, 2016-07-14 14:29:15, -69, 22:22:22:22:22:23,null,^M']

答案 1 :(得分:2)

如果不改变行本身的格式,可能(我不知道解决方案的更广泛的上下文)一个简单的shell转换很合适(我知道它不是python解决方案)。

所以:

$ sort -t, -k2,2 sort_me_on_first_timestamp_field.txt 
3B:3F:B9:0A:83:E6, 2016-07-14 01:28:59, 2016-07-14 01:29:01, -36, 33:33:33:33:33:31,null,^M 
61:01:55:16:B5:52, 2016-07-14 06:25:32, 2016-07-14 06:25:34, -56, 33:33:33:33:33:33,null,^M
B3:C0:6E:77:E5:31, 2016-07-14 08:26:45, 2016-07-14 08:26:47, -65, 33:33:33:33:33:32,null,^M 
81:0A:D7:19:25:7B, 2016-07-14 14:29:13, 2016-07-14 14:29:15, -69, 22:22:22:22:22:23,null,^M 

对我来说很好看。 -t选项告诉sort使用逗号作为分隔符,-k2,2基于第二个“字段”请求排序(它从一开始计数)。有时用-n切换到数字排序很重要,但是这里的ISO datetime字符串是固定长度的,它应该与词法排序一起使用。

再说一遍:如果你正在寻找一个纯python解决方案,我建议选择建议的基于python的答案。这只是建议一个基线替代方案。

更新以“测量”某些机器上的某些情况 - 好吧:

在“开发者的机器”上,将样本4行连续多次连接成20,200,2000,...,2,000,000行的文件,从12毫秒到1.7秒(200万行)到使用sort命令写入/ dev / null并写入文件2秒。

@ juanpa.arrivillaga建议的路线排序的原始实施:

#! /usr/bin/env python
FILE_PATH_IN = './fhf.txt'
NL, FS = '\n', ','

list_of_strings = open(FILE_PATH_IN).read().split(NL)[:-1]
list_of_strings.sort(key=lambda s: s.split(FS)[1])
with open(FILE_PATH_IN + ".out", "wt") as f:
    f.write(NL.join(list_of_strings))

在同一台机器上需要大约。作为另一个变体(使用sorted来生成新列表)的200万行案例的3秒确实:

#! /usr/bin/env python
FILE_PATH_IN = './fhf.txt'
NL, FS = '\n', ','

list_of_strings = open(FILE_PATH_IN).read().split(NL)[:-1]
with open(FILE_PATH_IN + ".out", "wt") as f:
    f.write(NL.join(sorted(list_of_strings, key=lambda s: s.split(',')[1])))

所以建议使用纯python解决方案。

答案 2 :(得分:1)

你可以使用string.split(),string.split(',')[1]