Python中的CSV排序

Python中的CSV排序,python,sorting,csv,Python,Sorting,Csv,我假设使用Python在多个文本/数字字段上排序CSV文件将是一个已经解决的问题。但我在任何地方都找不到任何示例代码,除了专注于排序日期字段的特定代码 如何在多个字段上按顺序对相对较大的CSV文件(数万行)进行排序 Python代码示例将不胜感激。Python的排序只在内存中工作;然而,在一台现代机器上,数万行应该可以很容易地存储在内存中。因此: import csv def sortcsvbymanyfields(csvfilename, themanyfieldscolumnnumbers

我假设使用Python在多个文本/数字字段上排序CSV文件将是一个已经解决的问题。但我在任何地方都找不到任何示例代码,除了专注于排序日期字段的特定代码

如何在多个字段上按顺序对相对较大的CSV文件(数万行)进行排序


Python代码示例将不胜感激。

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)
你提出了3个问题:

  • 文件大小
  • csv数据
  • 多字段排序
这是第三部分的解决方案。您可以以更复杂的方式处理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']]

编辑为使用列表理解,生成器不能像我预期的那样工作。

以下是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)
编辑:

我做了一件蠢事。我在空闲状态下玩各种东西,几天前写了一个
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()

>>> 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函数可以执行您需要的操作,而不仅仅是类型强制<代码>无用于表示没有转换。

这就是为什么我需要花一个周末(或一周)来查看标准库参考。itemgetter看起来不错。我也很喜欢这个答案,因为它没有满足OP的“多文本/数字字段”要求;它将所有字段视为文本。@John,如果在排序之前需要对某些字段进行不同的处理(例如,进行多种不同类型的强制转换),这并不难安排,但是Q中没有足够的规范细节来说明如何通过函数参数来指定这样一个潜在的复杂问题(毫无疑问,单独的Q是值得的,因为除了排序之外,它可能非常重要!)--如果您想要这些信息,为什么不自己打开一个Q?顺便说一句,csv的第一行通常是一个标题-请小心在排序时忽略它convert()函数是什么?还有,第二个和第三个参数列表是吗?sort_csv('myfile.csv',[?,?,?,?],['Name','BirthDate','Age','Price']@Pranab:第二个和第三个参数都可以是任意一个iterableThe
convert
函数是,啊,我忘了包含的东西。请参见编辑。您可以使用类似于:
sort_csv('myfile.csv')的东西调用这个函数,(str,int,float,int),(2,3))
如果要按最后两列对四列CSV文件进行排序。