2007-08-31
Python Cookbook 4.7 在2维列表中删除或重排某些列
需求:
你有一个二维列表,需要重新获得一个列表,其中行不变,而将某些列重排或者删除.
讨论:
使用列表递推式可以处理这个问题,比如你有如下的列表:
listOfRows = [ [1,2,3,4], [5,6,7,8], [9,10,11,12] ]
现在你需要将第二列删除,并将第四列和第三列互换位置,用一个列表递推式就能出色的完成任务:
newList = [ [row[0], row[3], row[2]] for row in listOfRows ]
结果如下:
[[1, 4, 3], [5, 8, 7], [9, 12, 11]]
另外的办法,稍微复杂一些,是使用临时的列表来保存要调整的位置:
newList = [ [row[ci] for ci in (0, 3, 2)] for row in listofRows ]
我经常使用列表的列表来表示二维数组,而在处理这类问题的过程中经常遇到列的处理,比如重排某些列,忽略其中的一些数值等.使用列表递推式来处理这一类问题看起来不是那么显然.
列表递推式创建一个新列表,而不是改变原来的.但是即使你需要修改现有的列表,使用列表递推式然后赋值给现有列表也是很好的方法.比如,你想修改listOfRows,就按照本节的需求,你可能这样写:
listOfRows[:] = [ [row[0], row[3], row[2]] for row in listOfRows ]
但是请注意,遇到这样的问题,请是用本节给出的第二个列子的办法,用一个临时列表保存列的位置,而不是硬编码.也许你不喜欢将两个递推式嵌套起来,但是它会更安全一些.如果你使用这种方法,还能得到附加的好处,因为增强的灵活性,你可以将它封装成一个函数,将想要调整的顺序做为参数传递进去:
def pick_and_reorder_columns(listofRows, column_indexes):
return [ [row[ci] for ci in column_indexes] for row in listofRows ]
columns = 0, 3, 2
newListOfPandas = pick_and_reorder_columns(oldListOfPandas, columns)
newListOfCats = pick_and_reorder_columns(oldListOfCats, columns)
上面的代码和前面的 一样,调整了列表中列的顺序,但是它操作的是两个列表.
最后要注意的,有些人喜欢将列表递推式中的变量部分替换成函数返回值,而不是直接使用,比如在:
[row[ci] for ci in column_indexes]
可以使用map函数,用__getitem__来代替[],所以可以这样写:
map(row._ _getitem_ _, column_indexes)
取决于你的Python版本,也许map版的会更快一些.不过我坚持认为最简单的列表递推式是最好的 .
你有一个二维列表,需要重新获得一个列表,其中行不变,而将某些列重排或者删除.
讨论:
使用列表递推式可以处理这个问题,比如你有如下的列表:
listOfRows = [ [1,2,3,4], [5,6,7,8], [9,10,11,12] ]
现在你需要将第二列删除,并将第四列和第三列互换位置,用一个列表递推式就能出色的完成任务:
newList = [ [row[0], row[3], row[2]] for row in listOfRows ]
结果如下:
[[1, 4, 3], [5, 8, 7], [9, 12, 11]]
另外的办法,稍微复杂一些,是使用临时的列表来保存要调整的位置:
newList = [ [row[ci] for ci in (0, 3, 2)] for row in listofRows ]
我经常使用列表的列表来表示二维数组,而在处理这类问题的过程中经常遇到列的处理,比如重排某些列,忽略其中的一些数值等.使用列表递推式来处理这一类问题看起来不是那么显然.
列表递推式创建一个新列表,而不是改变原来的.但是即使你需要修改现有的列表,使用列表递推式然后赋值给现有列表也是很好的方法.比如,你想修改listOfRows,就按照本节的需求,你可能这样写:
listOfRows[:] = [ [row[0], row[3], row[2]] for row in listOfRows ]
但是请注意,遇到这样的问题,请是用本节给出的第二个列子的办法,用一个临时列表保存列的位置,而不是硬编码.也许你不喜欢将两个递推式嵌套起来,但是它会更安全一些.如果你使用这种方法,还能得到附加的好处,因为增强的灵活性,你可以将它封装成一个函数,将想要调整的顺序做为参数传递进去:
def pick_and_reorder_columns(listofRows, column_indexes):
return [ [row[ci] for ci in column_indexes] for row in listofRows ]
columns = 0, 3, 2
newListOfPandas = pick_and_reorder_columns(oldListOfPandas, columns)
newListOfCats = pick_and_reorder_columns(oldListOfCats, columns)
上面的代码和前面的 一样,调整了列表中列的顺序,但是它操作的是两个列表.
最后要注意的,有些人喜欢将列表递推式中的变量部分替换成函数返回值,而不是直接使用,比如在:
[row[ci] for ci in column_indexes]
可以使用map函数,用__getitem__来代替[],所以可以这样写:
map(row._ _getitem_ _, column_indexes)
取决于你的Python版本,也许map版的会更快一些.不过我坚持认为最简单的列表递推式是最好的 .