使用数字后缀对不同长度的字符串进行排序

时间:2013-07-22 10:06:33

标签: python string sorting

我有一个列表列表,基于我想要对列表进行排序的每个列表的第一个元素。这些指数的样本:

  vlan1                    
  usb0                   
  eth1                     
  vlan4                   
  vlan20  

如果它们的长度与vlanX相同,我会做类似的事情:

 table_data = sorted(table_data, key = lambda x: int(x[0][4:]))

我想以一种先出现的方式对它们进行排序,然后其余的并不重要。好的,如果它们已经分类但不是必需的(我认为不会有超过一个usb或eth)。

  vlan1
  vlan4 
  vlan20                    
  usb0                    
  eth1                                 

调整我的lambda是否很简单,或者我应该尝试创建一个函数吗?

我尝试了这一点,但显然它将usb和eth留在错误的地方,而不是对vlans进行排序。

table_data = sorted(table_data, key = lambda x: x = True if "vlan" not in x[0] else int(x[0][4:]))
编辑:那个帖子没有回答我的意思?这将在vlan元素之间对usb和eth元素进行排序,这不是我想要的。

1 个答案:

答案 0 :(得分:1)

您可以编写一个函数来拆分(前缀,索引)中的名称,并将其传递给key参数。

import re
table_data = ["vlan1", "usb0", "eth1", "vlan4", "vlan20"]

def get_key(v):
    prefix, index = re.match(r'([a-z]+)(\d+)', v).groups()
    return prefix, -int(index)

>>> sorted(table_data, key=get_key, reverse=True)
['vlan1', 'vlan4', 'vlan20', 'usb0', 'eth1']

您希望订单按前缀递减并按索引递增,该函数将索引转换为负数,因此当列表反转时,顺序正确。

[更新]

  

不,OP不希望订单按前缀降序。无论如何,OP都希望'vlan'先排序。这恰好适合降序字母排序,但如果“wlan”键被添加到数据中则不行。 - Martijn Pieters

足够公平。

def get_key(v):
    prefix, index = re.match(r'([a-z]+)(\d+)', v).groups()
    if prefix == 'vlan':
        prefix = '~'
    return prefix, -int(index)

>>> table_data = ["vlan1", "usb0", "eth1", "vlan4", "vlan20", "wlan0"]
>>> sorted(table_data, key=get_key, reverse=True)
['vlan1', 'vlan4', 'vlan20', 'wlan0', 'usb0', 'eth1']

如何组装一个词典?

interfaces = {}
for iface in table_data:
    prefix, index = re.match(r'([a-z]+)(\d+)', iface).groups()
    interfaces.setdefault(prefix, []).append(iface)
for v in interfaces.values():
    v.sort(key=lambda x: int(re.search(r'\d+', x).group(0)))

>>> interfaces
{'eth': ['eth1'],
 'usb': ['usb0'],
 'vlan': ['vlan1', 'vlan4', 'vlan20'],
 'wlan': ['wlan0']}

>>> interface_types = interfaces.keys()
>>> interface_types
['eth', 'vlan', 'wlan', 'usb']

>>> interfaces['vlan']
['vlan1', 'vlan4', 'vlan20']