【发布时间】:2011-01-06 12:54:51
【问题描述】:
我假设使用 Python 对多个文本/数字字段上的 CSV 文件进行排序将是一个已经解决的问题。但是我在任何地方都找不到任何示例代码,除了专注于排序日期字段的特定代码。
如何按顺序对多个字段上的相对较大的 CSV 文件(数万行)进行排序?
Python 代码示例将不胜感激。
【问题讨论】:
我假设使用 Python 对多个文本/数字字段上的 CSV 文件进行排序将是一个已经解决的问题。但是我在任何地方都找不到任何示例代码,除了专注于排序日期字段的特定代码。
如何按顺序对多个字段上的相对较大的 CSV 文件(数万行)进行排序?
Python 代码示例将不胜感激。
【问题讨论】:
这是 Alex 的答案,经过重新设计以支持列数据类型:
import csv
import operator
def sort_csv(csv_filename, types, sort_key_columns):
"""sort (and rewrite) a csv file.
types: data types (conversion functions) for each column in the file
sort_key_columns: column numbers of columns to sort by"""
data = []
with open(csv_filename, 'rb') as f:
for row in csv.reader(f):
data.append(convert(types, row))
data.sort(key=operator.itemgetter(*sort_key_columns))
with open(csv_filename, 'wb') as f:
csv.writer(f).writerows(data)
编辑:
我做了一个傻事。几天前,我在 IDLE 中玩各种东西,并写了一个 convert 函数。我忘了我已经写过了,而且我很久没有关闭 IDLE - 所以当我写上面的时候,我认为convert 是一个内置函数。可惜没有。
这是我的实现,虽然 John Machin 的更好:
def convert(types, values):
return [t(v) for t, v in zip(types, values)]
用法:
import datetime
def date(s):
return datetime.strptime(s, '%m/%d/%y')
>>> convert((int, date, str), ('1', '2/15/09', 'z'))
[1, datetime.datetime(2009, 2, 15, 0, 0), 'z']
【讨论】:
convert 函数是啊,我忘记包含了。见编辑。如果您想按最后两列对四列 CSV 文件进行排序,您可以使用类似 sort_csv('myfile.csv', (str, int, float, int), (2, 3)) 的方式调用此函数。
这是罗伯特修复亚历克斯答案中缺少的convert():
>>> def convert(convert_funcs, seq):
... return [
... item if func is None else func(item)
... for func, item in zip(convert_funcs, seq)
... ]
...
>>> convert(
... (None, float, lambda x: x.strip().lower()),
... [" text ", "123.45", " TEXT "]
... )
[' text ', 123.45, 'text']
>>>
我更改了第一个参数的名称,以强调 per-columns 函数可以满足您的需求,而不仅仅是类型强制。 None 用于表示没有转化。
【讨论】:
你提出了 3 个问题:
这是第三部分的解决方案。您可以以更复杂的方式处理 csv 数据。
>>> data = 'a,b,c\nb,b,a\nb,c,a\n'
>>> lines = [e.split(',') for e in data.strip().split('\n')]
>>> lines
[['a', 'b', 'c'], ['b', 'b', 'a'], ['b', 'c', 'a']]
>>> def f(e):
... field_order = [2,1]
... return [e[i] for i in field_order]
...
>>> sorted(lines, key=f)
[['b', 'b', 'a'], ['b', 'c', 'a'], ['a', 'b', 'c']]
编辑为使用列表推导,生成器无法像我预期的那样工作。
【讨论】:
Python 的排序只在内存中工作;然而,在现代机器上,数以万计的行应该很容易放入内存中。所以:
import csv
def sortcsvbymanyfields(csvfilename, themanyfieldscolumnnumbers):
with open(csvfilename, 'rb') as f:
readit = csv.reader(f)
thedata = list(readit)
thedata.sort(key=operator.itemgetter(*themanyfieldscolumnnumbers))
with open(csvfilename, 'wb') as f:
writeit = csv.writer(f)
writeit.writerows(thedata)
【讨论】: