如何对一个列表进行排序,只排序字符串?

5

我有一个由字符串和整数组成的列表,想要对列表进行排序,同时保留数字的顺序,如下所示

["Hello", 1, 2, "World", 6, "Foo", 3]

将会变得

["Foo", 1, 2, "Hello", 6, "World", 3]

简而言之,它只对列表中的字符串进行排序,不会对整数进行排序,而整数仍然保持原位。我尝试使用 list.sort()key 参数,但未能实现我想要的效果。
有人能帮助我吗?
编辑:这与链接问题不同,因为我想保留整数的索引,而不是将它们与字符串一起排序。
编辑:这与第二个链接问题不同,因为该问题的答案可以使用 key 参数解决问题,而我已明确声明在这种情况下不起作用。

不确定为什么我的评论被删除了,这肯定是相关的:https://dev59.com/9VkR5IYBdhLWcg3w2wp1 - Chris_Rands
3个回答

15

前几天从 @JonClements 学到了这个很酷的技巧。

废话不多说:

gen = iter(sorted([x for x in lst if isinstance(x, str)]))
new_lst =  [next(gen) if isinstance(x, str) else x for x in lst]
print(new_lst)
# ['Foo', 1, 2, 'Hello', 6, 'World', 3]

将字符串分别排序,并从排序后的字符串创建生成器表达式。在一个 列表推导式 中,使用三目运算符交替从生成器表达式中挑选对象,当原始位置上的项目为字符串时,仅选择该项目,否则从初始列表中选择一个项(整数)。


我实际上点赞了这个解决方案。但我知道有些人会根据你的解决方案是O(n^2)并且将原始数组的内存占用量翻倍而投反对票。 - Matthew Cole
@MosesKoledoye,我看到了一个有关奇偶数的模拟问答。那是同一个吗? - Jean-François Fabre
4
如果存在一种懒惰的排序算法,这将是更美好的唯一途径。 - juanpa.arrivillaga
2
@MosesKoledoye 可以通过强制在 sort 中使用列表推导式来稍微提高速度:gen = iter(sorted([x for x in l if isinstance(x,str)])),因为它无论如何都需要构建它。(顺便说一句,我们在这个网站上花费了太多时间) - Jean-François Fabre
@MatthewCole 你怎么判断这是O(n^2)的? - juanpa.arrivillaga
显示剩余6条评论

8

首先,这样的异构列表排序仅适用于Python 2。但结果并不是您所需的。

我会在经过筛选的列表上创建一个迭代器(仅保留字符串),并使用迭代器中的项或原始列表中的项重新构建列表,具体取决于元素类型:

l = ["Hello", 1, 2, "World", 6, "Foo", 3]

sgen = iter(sorted([x for x in l if isinstance(x,str)]))

result = [next(sgen) if isinstance(x,str) else x for x in l]

print(result)

结果:

['Foo', 1, 2, 'Hello', 6, 'World', 3]

0

首先,您只需使用字符串对数组进行排序,然后逐步在原始数组中替换字符串:

l = ["Foo", 1, 2, "Hello", 6, "World", 3]

s = [x for x in l if type(x) == str]
s.sort()

j = 0
for i, x in enumerate(l):
    if type(x) == str:
       l[i] = s[j]
       j += 1

虽然这段代码可能回答了问题,但是提供关于为什么和/或如何回答问题的额外上下文可以提高其长期价值。 - Donald Duck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接