简体   繁体   English

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

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

I have this tuple:我有这个元组:

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

I would like to classify it in this order:我想按以下顺序对其进行分类:

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

To have: [('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 idea is to first classify the NFV part in ascending order,after that, we classify the SWSTO in increasing order too but by putting the SWSTO which ends with 'V' first 574的想法是首先按升序对NFV部分进行分类,然后,我们也按升序对SWSTO进行分类,但是将以'V'结尾的SWSTO放在第一位

How can I do that?我怎样才能做到这一点?

Note that Python already sorts tuples naturally, first sorting on the first element, then the second element, etc. That means that if we can create a tuple which reflects the appropriate ranking of your elements, we can simply sort using that tuple as a key.请注意,Python 已经自然地对元组进行了排序,首先对第一个元素进行排序,然后对第二个元素进行排序,等等。这意味着如果我们可以创建一个反映元素适当排名的元组,我们可以简单地使用该元组作为键进行排序.

To convert your sorting pattern to a tuple, treat the presence of 'V' as negative infinity, and otherwise use the number.要将您的排序模式转换为元组,请将“V”的存在视为负无穷大,否则使用该数字。

Last, we can use conveniences of Python like zip and re to reduce the lines of code to get there.最后,我们可以使用 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'
# )

Or, for a one-liner (don't do this:):或者,对于单线(不要这样做:):

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]

The best way would be to use key argument for sorted function.最好的方法是对sorted的 function 使用key参数。

from docs :来自文档

The value of the key parameter should be a function that takes a single argument and returns a key to use for sorting purposes. key 参数的值应该是一个 function,它接受一个参数并返回一个用于排序目的的键。 This technique is fast because the key function is called exactly once for each input record.这种技术很快,因为每个输入记录只调用一次键 function。

to sort your list of codes I would do something like this:要对您的代码列表进行排序,我会执行以下操作:

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')

If you don't know how lambda expressions work check out the docs .如果您不知道 lambda 表达式如何工作,请查看文档

I found it way clearer to make a standalone keying function:我发现制作独立键控 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))

This lets you be super explicit about how the sorting key is generated, as is vastly easier to test.这使您可以非常明确地了解排序键是如何生成的,因为它更容易测试。

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

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