如何使用特定规则使用python对元组进行排序

时间:2020-06-02 22:00:56

标签: python tuples

我有这个元组:

[('site-nfv01-swsto01',), ('site-nfv01-swsto01V',),('site-nfv01-swsto02',),('site-nfv02-swsto02',), ('site-nfv02-swsto01',) , ('site-nfv02-swsto01V',)]

我想按以下顺序对其进行分类:

site-nfv01-swsto01V
site-nfv01-swsto01
site-nfv01-swsto02
site-nfv02-swsto01V
site-nfv02-swsto01
site-nfv02-swsto02

拥有:[('site-nfv01-swsto01V',), ('site-nfv01-swsto01',),('site-nfv01-swsto02',),('site-nfv02-swsto01V',), ('site-nfv02-swsto01',) , ('site-nfv02-swsto02',)]

574的想法是首先按升序对NFV部分进行分类,此后,我们也对SWSTO进行升序分类,但将以'V'结尾的SWSTO放在首位

我该怎么做?

3 个答案:

答案 0 :(得分:1)

请注意,Python已经自然地对元组进行了排序,首先对第一个元素进行排序,然后对第二个元素进行排序,依此类推。这意味着,如果我们可以创建一个反映您元素的适当排名的元组,则可以简单地使用该元组进行排序作为键。

要将排序模式转换为元组,请将'V'的存在视为负无穷大,否则使用数字。

最后,我们可以使用Python的便利性,例如zipre来减少到达那里的代码行。

import re
from math import inf
def sorted_tuples(string_list):
    def rank(chunk):
        if 'V' in chunk:
            return -inf
        return int(re.findall(r"\d+", chunk)[0])

    items = [(word, word.split('-')) for (word,) in string_list]
    keys = [(word, rank(chunks[1]), rank(chunks[2])) for (word, chunks) in items]
    keys.sort(key=lambda x: (x[1], x[2]))
    return list(zip(*keys))[0]


print(sorted_tuples([
     ('site-nfv01-swsto01V',), 
     ('site-nfv01-swsto01',),
     ('site-nfv01-swsto02',),
     ('site-nfv02-swsto01V',), 
     ('site-nfv02-swsto01',) , 
     ('site-nfv02-swsto02',)]))

# Outputs:
# ('site-nfv01-swsto01V', 
#     'site-nfv01-swsto01', 
#     'site-nfv01-swsto02', 
#     'site-nfv02-swsto01V', 
#     'site-nfv02-swsto01', 
#     'site-nfv02-swsto02'
# )

或者,单线(不要这样做!):

lambda string_list: list(zip(*sorted([(word, list(map(lambda x: -inf \
     if 'V' in x else int(re.findall(r"\d+", x)[0]), word.split('-') \
     [1:]))) for (word,) in string_list], key=lambda x: x[1])))[0]

答案 1 :(得分:1)

最好的方法是对key函数使用sorted参数。

来自docs

key参数的值应为采用 单个参数,并返回用于排序目的的键。这个 技术是快速的,因为关键函数只被调用一次 每个输入记录。

要对您的代码列表进行排序,我会这样做:

your_list = [('site-nfv01-swsto01',), ('site-nfv01-swsto01V',),('site-nfv01-swsto02',),('site-nfv02-swsto02',), ('site-nfv02-swsto01',) , ('site-nfv02-swsto01V',)]
#sort using key parameter
#key must be a function that returns a new value to be sorted
#this particular key function checks if 'V' is at the last position, 
#leaves the code unchanged if true,
#else adds arbitrary string at the end of the code that will cause the code to be sorted after codes with the same content at the beginning but lacking the 'V'
#in this case I chose 'z' which comes after 'v' in the alphabet
sorted_list = sorted(your_list, key=lambda code: code[0] if code[0][-1] == 'V'  else code[0]+'z')

如果您不知道lambda表达式的工作原理,请查看docs

答案 2 :(得分:1)

我发现可以更轻松地制作独立的键控功能:

#!/usr/bin/env python

lst = [
    ("site-nfv01-swsto01",),
    ("site-nfv01-swsto01V",),
    ("site-nfv01-swsto02",),
    ("site-nfv02-swsto02",),
    ("site-nfv02-swsto01",),
    ("site-nfv02-swsto01V",),
]


def my_key(item):
    """Return a tuple that can be used for ordering the item."""

    first, middle, last = item[0].split("-")

    # For the middle part, what we really care about is the int after the "nfv" string.
    middle_int = int(middle[3:])

    # For the last part, we mostly care about the int after the "swsto" string...
    last_value = last[5:]

    # ...but not quite. Let's make sure that items with a trailing "V" sort lower than ones without
    # a "V".
    if last_value.endswith("V"):
        last_tuple = int(last_value[:-1]), "V"
    else:
        last_tuple = int(last_value), "z"

    # Python sorts tuples one component at a time, so return a tuple that can be compared against
    # the tuples generated for other values.
    return first, middle_int, last_tuple


# For demonstration purposes, show the sorting key generated for each item in the list.
for item in lst:
    print(item, my_key(item))

# Use that sorting key to actually sort the list.
print(sorted(lst, key=my_key))

这使您可以非常明确地了解排序密钥的生成方式,这非常容易测试。