用一个列表理解和两个条件对列表重新排序

问题描述

就像在锡罐上说的那样。假设我有一个字符串列表: 水果= ['蓝莓','杏','苹果','鳄梨','香蕉','杏','黑莓']

假设我想重新排序,结果以“ a”开头,然后是所有“ b”结果-不是按字母顺序,而是按照它们在列表中出现的顺序。因此,杏将成为重新排序列表中的第一项。蓝莓先于香蕉等。

这很简单,有两个列表理解,甚至只是:

fruits = ['blueberries','apricot','apple','avocado','banana','blackberries']
    
a_fruit = [x for x in fruits if x[0] == 'a']
b_fruit = [x for x in fruits if x[0] == 'b']
    
print(a_fruit + b_fruit)

['apricot','blueberries','blackberries']

是否可以使用-one-列表理解来做到这一点?我认为if-else不会起作用,因为那只会遍历列表一次。我认为这必须是某种嵌套的列表理解,它会遍历列表两次,首先添加'a'项,然后再添加'b'项,但是我一直无法弄清楚,并以为我d再次确认我要执行的操作并非不可能。

即使有可能-会更好吗?似乎代码很难阅读...

编辑:我需要澄清的是,我正在寻找一种可以在任意两个条件下使用的通用解决方案-由于通用条件可能不使用字符串等,因此我想避免使用'sort'。

解决方法

这里最好的解决方案不是listcomp,而是排序。只要做:

sorted_fruit = sorted(fruits,key=lambda x: x[0])

,它将把a放在b之前,同时保持现有顺序。

如果您真的坚持使用listcomp,则可以执行la的嵌套循环结构:

sorted_fruit = [x for prefix in 'ab' for x in fruits if x[0] == prefix]

对于每个前缀,循环fruits一次,因此它在单个listcomp中完成了两个listcomp的所有工作;与在性能上并置两个listcomp的结果相比,这有一点改进(因为它直接构建最终的list,而不是两个临时list会被丢弃以构建第三个list ),但在我看来很难。

从理论上讲,它比排序要快(这是两个O(n)操作,而不是一个O(n log n)操作),但在实践中可能会比较慢(给定sorted是用C实现的内置功能,并且排序操作非常简单),除非输入变得非常大。

,

我想说,最优雅的方式是根据第一个字符对列表进行排序:

>>> sorted(fruits,key=lambda fruit: fruit[0])
['apricot','apple','avocado','apricot','blueberries','banana','blackberries']

或者,您可以像这样嵌套理解:

>>> [f for c in 'ab' for f in fruits if f[0] == c]
['apricot','blackberries']