按非常特殊的键

时间:2018-05-24 18:07:10

标签: python sorting lambda key

我必须以与sorted函数非常相似的方式对字符串列表进行排序,但有一个重要的区别。如您所知,sorted函数会占用空格字符前一个数字字符,因此sorted(['1 ', ' 9'])会为我们提供[' 9', '1 ']。我需要sorted来计算空格字符之前的数字字符,因此在我们的示例中,结果将为['1 ', ' 9']

更新

据我了解,默认情况下,sorted行为依赖于ascii'字母表中的字符顺序' (即''.join([chr(i) for i in range(59, 127)])),所以我决定实施自己的ascii'字母表'在my_ord函数中。

我计划将此功能与简单my_sort功能结合使用,作为sorted的键,

def my_ord(c):
    punctuation1 = ''.join([chr(i) for i in range(32, 48)])
    other_stuff = ''.join([chr(i) for i in range(59, 127)])
    my_alphabet = string.digits + punctuation1 + other_stuff
    return my_alphabet.find(c)

def my_sort(w):
    return sorted(w, key=my_ord)

像这样:sorted([' 1 ', 'abc', ' zz zz', '9 '], key=my_sort)

我在这种情况下期待的是['9 ', ' 1 ', ' zz zz', 'abc']。不幸的是,结果不仅与预期不符 - 而且,它不时有所不同。

4 个答案:

答案 0 :(得分:2)

您可以使用lstrip作为关键函数来忽略字符串左前方的空格。

r = sorted(['1 ', ' 9' , ' 4', '2 '], key=str.lstrip)
# r == ['1 ', '2 ', ' 4', ' 9']
  

key指定一个参数的函数,用于从每个列表元素doc中提取比较键。

答案 1 :(得分:1)

试试这个

import string
MY_ALPHABET = (
        string.digits
        + ''.join([chr(i) for i in range(32, 127) if chr(i) not in string.digits])
)
inp = [' 1 ', 'abc', ' zz zz', '9 ', 'a 1', 'a ']
print(inp, '-->', sorted(inp, key=lambda w: [MY_ALPHABET.index(c) for c in w]))

答案 2 :(得分:0)

您需要词法和数字排序的组合。您可以通过将字符串切换为元组并将数字转换为int来实现。现在,元组比较将根据自己的比较规则考虑每个元素。

我使用正则表达式将字符串拆分为(开始文本,空格,数字,其他所有内容)创建int并将其用于密钥。如果字符串与模式不匹配,它只返回元组中的原始字符串,以便它也可以用于比较。

我在数字之后移动了数字(组(2))之前的空格,但是将它完全从比较中删除可能更有意义。

import re

test = ['1  ', ' 9']
wanted = ['1  ', ' 9']

def sort_key(val):
    """Return tuple of (text, int, spaces, remainder) or just
    (text) suitable for sorting text lexagraphically but embedded
    number numerically"""
    m = re.match(r"(.*?)(\s*)(\d+)(.*)", val)
    if m:
        return (m.group(1), int(m.group(3)), m.group(2), m.group(4))
    else:
        return (val,)

result = sorted(test, key=sort_key)
print(test, '-->', result)
assert result == wanted, "results compare"

答案 3 :(得分:0)

为了完整性和极端情况下的效率,这里有一个使用numpy argsort的解决方案:

UIViewController

总的来说,我认为使用sorted(...,key = ...)通常是优越的,如果输入已经是一个numpy数组,这个解决方案更有意义。另一方面,它每个项目只使用一次strip()并使用numpy,因此对于足够大的列表,它可能更快。此外,它会生成顺序,whitch显示每个已排序元素在原始列表中的位置。

作为最后一条评论,从您提供的代码中,但不是您提供的示例,我不确定您是否只想剥离前导空格,或者执行更多操作,例如: best-way-to-strip-punctuation-from-a-string-in-python,或者没有标点符号的字符串上的第一个顺序,然后如果它们相等,则按顺序排序(tdelaney的解决方案)无论如何编译模式可能不是一个坏主意,例如

import numpy as np
lst = ['1 ', ' 9' , ' 4', '2 ']
order = np.argsort(np.array([s.lstrip() for s in lst]))
result = list(np.array(lst)[order])

或:

import numpy as np
import re
pattern = re.compile(r'[^\w]')
lst = ['1 ', ' 9' , ' 4', '2 ']
order = np.argsort(np.array([pattern.sub('',s) for s in lst]))
result = list(np.array(lst)[order])