用python排序csv文件

时间:2014-09-22 01:39:29

标签: python sorting csv

我正在尝试按列对csv文件进行排序。该文件有许多列,如下所示:

汤姆,01AA01,234.56,334

翘,01AS01,546.09,3434.3

山姆,01NA01,4574.3,65.45

乐,01BA01,2897.03,455

帕姆,01MA01,434.034,454

约翰,01AA02,343,24

翘,01AS02,454,454.54

汤姆,02BA01,3434,3454.2

它继续大约20列和250行。

我希望它按第二列排序,并按字母顺序排列第二部分中的AAASBA,以及数字上第三部分'01',' 02','03',数字上为第一部分'01','02','03'。然后从这种类型创建一个新的csv文件。它们通常不只有6个字符,其他看起来像'02BAA','01MAA','02NAA'等等。

所以最终希望第2列看起来像这样。

01AA01
01AS01
01BA01
01MA01
01NA01
01AA02
01AS02
02BA01

我是编码的新手,并不太清楚如何去做。提前谢谢。

3 个答案:

答案 0 :(得分:1)

来自Python的sorted函数的ASCII字符串的默认排序顺序是lexicographic(或'ASCIIbetical'):

>>> li=['1', '20', '100', '11']
>>> sorted(li)
['1', '100', '11', '20']

与整数幅度相比,这些列表值是整数:

>>> sorted(map(int, li))
[1, 11, 20, 100]

即,人眼中弦的数量的大小与计算机眼中的相同弦的大小不同。 (更详尽地写在Codinghorror

要修复它,我们需要将数字与数字分开,并将数字转换为整数(或浮点数)。

最简单的方法是使用正则表达式捕获所有数字,然后将所有数字转换为整数。

这将分类到您的目标中:

li1='''\
01AA01
01AS01
01NA01
01BA01
01MA01
01AA02
01AS02
02BA01'''.splitlines()

tgt='''\
01AA01
01AS01
01BA01
01MA01
01NA01
01AA02
01AS02
02BA01'''.splitlines()


import re

def kf(s):
    nums=map(int, re.findall(r'(\d+)', s)) 
    lets=re.findall(r'([a-zA-Z]+)', s)
    return nums+lets   

print tgt==sorted(li1, key=kf)
# True

或者,一行:

>>> tgt==sorted(li1, key=lambda s: map(int, re.findall(r'(\d+)', s))+re.findall(r'(\D+)', s))
True

根据评论进行修改

问题的文字表明:

  

我希望在第一部分01,02,03中以数字方式订购...   然后按字母顺序排列第二部分的AA,AS,BA,和   数字再次为第三部分。

但是,示例表明情况并非如此。

我们可以使用split:

对(int,letters,int)的模式进行排序
>>> [re.split(r'(\D+)', e) for e in li1]
[['01', 'AA', '01'], ['01', 'AS', '01'], ['01', 'NA', '01'], ['01', 'BA', '01'], ['01', 'MA', '01'], ['01', 'AA', '02'], ['01', 'AS', '02'], ['02', 'BA', '01']]
>>> sorted(li1, key=lambda s: [int(e) if e.isdigit() else e for e in re.split(r'(\D+)', s)])
['01AA01', '01AA02', '01AS01', '01AS02', '01BA01', '01MA01', '01NA01', '02BA01']
#             ^^        ^^        etc '01AA02', before '01AS01' in the example

通过检查,POSTED示例的模式为(int, int, letters),可以在此处看到:

>>> [map(int, re.findall(r'(\d+)', s))+re.findall(r'(\D+)', s) for s in li1]
[[1, 1, 'AA'], [1, 1, 'AS'], [1, 1, 'NA'], [1, 1, 'BA'], [1, 1, 'MA'], [1, 2, 'AA'], [1, 2, 'AS'], [2, 1, 'BA']]

如果 TEXT 是正确的,请使用我所拥有的拆分形式;如果 EXAMPLE 正确,请使用nums+lets表单。

答案 1 :(得分:0)

sorted()和列表的.sort()方法采用可选的key参数。

<强>其中:

  

key 指定一个参数的函数,用于提取   每个列表元素的比较键:key = str.lower。

换句话说,给予key参数的函数(你将要编写)解析并返回给定对象的 sortable 值。

因此,根据您的输入"01AS01",您希望将其分解为可以轻松排序的部分。

正如您所提到的,您希望按( int,str,int )排序结果。由于sorted().sort()会自动按数字排序,(如果是),按字母顺序排列,(如果是字符串),您只需要为您的关键功能做的就是打破您的价值,"01AS01"进入[1, "AS", 1],而sorted() / .sort()会处理其余的事情。

这是与dawg相似的示例,但未使用map()re

col = ['01AA01',
 '01AS01',
 '01NA01',
 '01BA01',
 '01MA01',
 '01AA02',
 '01AS02',
 '02BA01'] 

def create_sort_key(value):
    int_indexes = (0, 4)
    str_indexes = (2,)
    parsed_values = []
    # get the starting index for groups of two
    for i in range(0, 6, 2):
        pair = value[i:i+2]
        if i in int_indexes:
            parsed_value = int(pair)
        elif i in str_indexes:
            parsed_value = str(pair)
        else:
            raise IndexError("unexpected index: {}".format(i))
        parsed_values.append(parsed_value)
    return parsed_values

col.sort(key=create_sort_key)

答案 2 :(得分:0)

假设这是一个csv文件,每行都是一行,每列都用逗号标记。既然没有给我们一个你的csv的例子,我组成了一个有两列,你的数据在col [1]。

>>> print open('mycsv.csv').read()
fred, 01AA01
brenda, 01BA01
bob, 01AA02
alice, 01NA01
jane, 01AS01
blane, 02BA01
larry, 01MA01
mary, 01AS02

这些都可以通过csv模块读入列表。最终得到一个行列表,其中列是另一个列表

>>> import csv
>>> table=[row for row in csv.reader(open('mycsv.csv')) if row]
>>> print table
[['fred', ' 01AA01'], ['brenda', ' 01BA01'], ['bob', ' 01AA02'], ['alice', ' 01NA01'], ['jane', ' 01AS01'], ['blane', ' 02BA01'], ['larry', ' 01MA01'], ['mary', ' 01AS02']]

您可以对该列表进行排序。默认情况下,排序从第一个键开始,然后是第二个键,如果第一个键是相同的,等等。因此,它将由#fred&#39;等...但您可以选择不同的排序键。 Python使用每个列表项调用键函数,以便您可以将其转换为您想要的。转换可以很简单,比如小写或复杂。

将lambda用于排序键是常见的,但这可能有点高级,所以这里只是抓住你想要的键的功能。

>>> def item_1(row):
...     return row[1]
... 
>>> print table
[['fred', ' 01AA01'], ['bob', ' 01AA02'], ['jane', ' 01AS01'], ['mary', ' 01AS02'], ['brenda', ' 01BA01'], ['larry', ' 01MA01'], ['alice', ' 01NA01'], ['blane', ' 02BA01']]
>>>