我目前有一个列表列表,例如:
[['NJ', '10', '2000', '500', '20', '02-03-19', '15:20'],
['NJ', '15', '1500', '600', '20', '02-03-19', '15:30'],
['NYC', '25', '1500', '500', '10', '02-03-19', '15:30'],
['NYC', '15', '1200', '700', '1', '02-03-19', '15:35']]
我需要考虑几个元素对它们进行排序,例如,就索引号而言,0是面积,1是重量,2是距离,3是高度,4是自主性,5是日期而6是时间戳。我已经使用此命令对所有元素进行了排序:
list.sort(key=itemgetter(0, time_sorter, 4, 3))
其中time_sorter()是我先前构建的功能,可以根据元素时间戳对列表进行排序。我的问题是我需要在考虑“区域”的情况下对该列表进行排序。例如,说我需要像我一样对所有这些元素进行排序,但是我也想同时对它进行排序,以使在其0索引位置上带有“ NYC”的元素排在第一位。 ,我该如何处理?
奖励问题是:如果我在itemgetter()
或 sort “ key”参数本身中有多个参数,并且我希望排序相反,但仅对其中一个参数进行排序,我该怎么做?
我的最佳选择是将所有这些 sorts 分离为几个函数,然后在 sort 键中调用那些吗?
谢谢!
答案 0 :(得分:2)
使函数返回每个项目的排序键。该函数将被多次调用,每次都以单个项目作为参数,并且您可以根据需要在其中调用其他函数。
def _key(row):
return row[0], time_sorter(row), row[4], row[3]
无论您退回的物品如何,都将用于对物品进行排序:
mylist.sort(key=_key)
itemgetter
只是一个简单的函数工厂,它创建一个函数来获取项目。如果您需要更复杂的功能,则应自己创建函数
答案 1 :(得分:1)
使用数字,您可以通过有选择地使用减号(例如,)来反转某些键的排序,但不能反转其他键的排序。 vectors.sort(key=lambda v: (v.x, -v.y))
首先按vectors
组件的升序对x
的列表进行排序,然后按y
组件按降序的顺序对决。不幸的是,没有等效的方法可以对字符串进行处理。
一个不错的选择是编写一个类,将数据表示为对象而不是列表,并在类上定义自定义顺序。 functools.total_ordering装饰器使此操作变得更容易,因此您只需要定义__eq__
和__lt__
即可,而不必定义所有六个比较方法:
from functools import total_ordering
@total_ordering
class PlaceAndTime:
def __init__(self, area, weight, distance, height, autonomy, date, time):
self.area = area
self.weight = weight
self.distance = distance
self.height = height
self.autonomy = autonomy
self.date = date
self.time = time
def __eq__(self, other):
return self.__dict__ == other.__dict__
def __lt__(self, other):
# test whether self < other
if not isinstance(other, PlaceAndTime):
raise ValueError('Not comparable')
elif self.area != other.area:
# sort by area in reverse order using > instead of <
return self.area > other.area
elif self.date != other.date:
return self.date < other.date
elif self.time != other.time:
return self.time < other.time
elif self.autonomy != other.autonomy:
# sort by autonomy in reverse order using > instead of <
return self.autonomy > other.autonomy
else:
return self.height < other.height
这样,您可以简单地使用objects.sort()
对对象列表进行排序,而无需提供密钥。如果您特别想在列表的开头对'NYC'
这样的区域进行排序,则仍然可以使用自定义键:
objects.sort(key=lambda obj: (obj.area != 'NYC', obj))
之所以可行,是因为当obj.area == 'NYC'
时比较将是False
,否则它将是True
,因此比较False < True
意味着'NYC'
将出现在其他位置之前区域。
写课可能还会带来其他好处,例如它使您可以编写obj.time
而不是描述性较低的lst[6]
,并且可以编写其他方法来简化代码的其他部分。