如何根据字符串的存在对列表进行排序?

问题描述 投票:-1回答:2

我目前有一个列表清单,类似这样的东西:

[['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吗?

提前感谢!
python list sorting
2个回答
2
投票
使函数返回每个项目的排序键。该函数将被多次调用,每次都以单个项目作为参数,如果需要,您可以在其中调用其他函数。

def _key(row): return row[0], time_sorter(row), row[4], row[3]

无论您退回的物品如何,都将用于对物品进行排序:

mylist.sort(key=_key)

itemgetter只是一个简单的函数工厂,它创建一个函数来获取项目。如果您需要更复杂的功能,则应自己创建功能

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],并且可以编写其他方法来简化代码的其他部分。

© www.soinside.com 2019 - 2024. All rights reserved.