问题描述
就像在锡罐上说的那样。假设我有一个字符串列表: 水果= ['蓝莓','杏','苹果','鳄梨','香蕉','杏','黑莓']
假设我想重新排序,结果以“ 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']