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

时间:2019-12-10 17:50:34

标签: python list sorting

我目前有一个列表列表,例如:

[['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 键中调用那些吗?

谢谢!

2 个答案:

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