繁体   English   中英

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

[英]How to sort tuple with python by using specific rules

我有这个元组:

[('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放在第一位

我怎样才能做到这一点?

请注意,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]

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

来自文档

key 参数的值应该是一个 function,它接受一个参数并返回一个用于排序目的的键。 这种技术很快,因为每个输入记录只调用一次键 function。

要对您的代码列表进行排序,我会执行以下操作:

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 表达式如何工作,请查看文档

我发现制作独立键控 function 更清晰:

#!/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))

这使您可以非常明确地了解排序键是如何生成的,因为它更容易测试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM