【问题标题】:Sorting a combined list of numbers and letters in Python在 Python 中对数字和字母的组合列表进行排序
【发布时间】:2016-09-02 10:17:18
【问题描述】:

我正在尝试在 Python 中对一个列表进行排序,但一个列表在同一个术语中同时包含字母和数字。对字符串使用 sort 的问题是它不能正确地对数字进行排序:

2
23
3

list = [("a", ['8', '0']), ("a", ['7', '0b']), ("a", ['7', '0']), ("a", ['6', '0b']), ("a", ['6', '01']]

new_list = sorted(list, key=lambda i: i[1]) 
# works great on ints.

字母需要按数字等值排序,即:

a = 1, b = 2, c = 3, d = 4 etc

因此4.1a == 4.11

但我需要保留输出中的字母,而不仅仅是将其转换为 int。有什么想法吗?

【问题讨论】:

  • 您所显示的输入的预期结果是什么?
  • 写一个函数,将i[1]转换为字符串,将字符串中的a替换为1,将b替换为2等,然后返回转换为float的字符串,并使用那就像key?
  • 以上听起来很完美。将尝试弄清楚如何做到这一点(我是高级 python 的新手)。
  • 你能保证大于i的字母永远不会出现在数据中吗?否则,大于i 的字母会怎样?例如,j 是否被视为 0 或 10?

标签: python list python-2.7 sorting


【解决方案1】:

这是我的解决方案:

def f(s):
    m = {'a': 1,'b': 2,'c': 3,'d': 4,'e': 5,
         'f': 6,'g': 7,'h': 8,'i': 9,'j': 10,
         'k': 11,'l': 12,'m': 13,'n': 14,'o': 15,
         'p': 16,'q': 17,'r': 18,'s': 19,
         't': 20,'u': 21,'v': 22,'w': 23,
         'x': 24,'y': 25,'z': 26}
    result = []
    for l in s:
        try:
            result.append(int(l))
        except ValueError:
            result.append(m[l])
    return result

list = [("a", ['8', '0']), ("a", ['7', '0b']), ("a", ['7', '0']), ("a", ['6', '0b']), ("a", ['6', '01'])]
new_list = sorted(list, key=lambda i: f(''.join(i[1])))

>>> new_list
[('a', ['6', '01']),
 ('a', ['6', '0b']),
 ('a', ['7', '0']),
 ('a', ['7', '0b']),
 ('a', ['8', '0'])]

该函数将 '60b' 之类的内容转换为 [6,0,2] (字母在映射字典之后转换为整数。然后 lambda 根据返回的列表进行排序。

【讨论】:

  • 我怀疑 OP 希望 ['7', '0'] 按排序顺序出现在 ['6', '01'] 之前。
  • @PM2Ring 我不这么认为,['7','0'] 应该是 7.0 版,是 6.01 版之后的版本。如果你是对的,在 lambda 表达式中将 f(''.join(i[1])) 更改为 f(i[1][1]) 就足够了。
【解决方案2】:

您的问题并不完全清楚,但我假设您忽略了每个元组中的第一项,而只对第二项中的列表进行排序。我还假设从“a”到“i”的只有个字母可以出现在该列表中。

转换 a -> 1, b -> 2, c -> 3, ... i -> 9 的简单方法是利用数字字符的 ASCII 码是连续的,因此小写字母。因此,每个字母与其对应的数字之间存在 48 的恒定偏移量。

因此,要将字符串列表转换为键,我们可以将所有字符串连接成一个字符串,然后将字符串中的每个字母 char 转换为其等效的数字 char,将生成的字符连接回单个字符串,然后转换将该字符串转换为整数。

lst = [
    ("a", ['8', '0']), 
    ("a", ['7', '0b']), 
    ("a", ['7', '0']), 
    ("a", ['6', '0b']), 
    ("a", ['6', '01']),
]

def keyfunc(t):
    a = [chr(ord(c) - 48) if 'a' <= c <= 'i' else c for c in ''.join(t[1])]
    return int(''.join(a))

new_lst = sorted(lst, key=keyfunc)
for row in new_lst:
    print(row)

输出

('a', ['7', '0'])
('a', ['8', '0'])
('a', ['6', '01'])
('a', ['6', '0b'])
('a', ['7', '0b'])

顺便说一句,您不应该使用 list 作为变量名,因为这会影响内置的 list 类型,并且会导致神秘的错误。

【讨论】:

    【解决方案3】:

    您是在进行增量排序还是仅按a1elements 排序?

    如果你真的需要得到一个字母的数值,你可以使用 string.ascii_letters.index(letter) 或者更好的是,如果您只需要字母的连续数字,aord(letter)。

    但我认为字母应该正确排序而不需要获取整数值。我认为问题在于分裂['a', 'a1']

    我不确定这是否是您需要的:

    def sort_func(item):
        try:
            return item[1][1][1]
        except:
            return item[1][1]
    
    # sort by the alphanumeric
    vals.sort(key=sort_func)
    # sort again by the number
    vals.sort(key=lambda i: int(i[1][0]))
    # sort again by the first letter
    vals.sort(key=lambda i:i[0])
    

    【讨论】:

      猜你喜欢
      • 2021-12-06
      • 2018-09-03
      • 1970-01-01
      • 2018-04-09
      • 2021-04-04
      • 2021-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多