我目前有一个列表清单,类似这样的东西:
[['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键中调用those吗?
提前感谢!def _key(row):
return row[0], time_sorter(row), row[4], row[3]
无论您退回的物品如何,都将用于对物品进行排序:
mylist.sort(key=_key)
itemgetter
只是一个简单的函数工厂,它创建一个函数来获取项目。如果您需要更复杂的功能,则应自己创建功能
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]
,并且可以编写其他方法来简化代码的其他部分。