写这个表达式的更pythonic方式?

时间:2010-11-02 11:41:35

标签: python sorting

我应该拿一个单词列表并对其进行排序,除了我需要先将所有以'x'开头的字符串分组。

这是我得到的:

list_1 = []
list_2 = []

for word in words:
  list_1.append(word) if word[0] == 'x' else list_2.append(word)

return sorted(list_1) + sorted(list_2)

但我觉得有一种更优雅的方式可以做到这一点......

修改

实施例: ['mix', 'xyz', 'apple', 'xanadu', 'aardvark']会产生['xanadu', 'xyz', 'aardvark', 'apple', 'mix']

8 个答案:

答案 0 :(得分:41)

>>> words = ['xoo', 'dsd', 'xdd']
>>> sorted(words, key=lambda x: (x[0] != 'x', x))
['xdd', 'xoo', 'dsd']

说明:key函数返回一对(元组)。第一个元素是FalseTrue,具体取决于字符串中的第一个字符是'x'FalseTrue之前排序,因此以'x'开头的字符串将在排序输出中排在第一位。元组中的第二个元素将用于比较第一个元素中相同的两个元素,因此所有以'x'开头的字符串将在它们之间进行排序,并且所有字符串不以{{1}开头将在他们自己之间进行分类。

答案 1 :(得分:9)

首先:当你的意思是“干净”时,不要再说“pythonic”了。这只是一个俗气的流行词。

不要使用那样的三元表达;它意味着用作表达式的一部分,而不是用作流控制。这更清洁:

for word in words:
    if word[0] == 'x':
        list_1.append(word)
    else:
        list_2.append(word)

你可以多改进一下 - 使用像这样的三元表达式很好:

for word in words:
    target = list_1 if word[0] == 'x' else list_2
    target.append(word)

如果words是容器而不是迭代器,则可以使用:

list_1 = [word for word in words if word[0] == 'x']
list_2 = [word for word in words if word[0] != 'x']

最后,我们可以废弃整件事,而是使用两种:

result = sorted(words)
result = sorted(result, key=lambda word: word[0] != 'x')

首先进行正常排序,然后使用Python排序的稳定属性将以“x”开头的单词移到前面,而不会改变排序。

答案 2 :(得分:6)

words = ['xoo', 'dsd', 'xdd']
list1 = [word for word in words if word[0] == 'x']
list2 = [word for word in words if word[0] != 'x']

答案 3 :(得分:5)

应该注意的是,在Python 2.4中添加了sorted。如果您希望更短的版本更清晰,更向后兼容,您也可以直接使用.sort()功能list还应该注意,在这种情况下使用x[0]样式数组索引语法时,空字符串将引发异常(正如许多示例所示)。 .startswith() should be used instead, as is properly used in Tony Veijalainen's answer

>>> words = ['mix', 'xyz', '', 'apple', 'xanadu', 'aardvark']
>>> words.sort(key=lambda x: (not x.startswith('x'), x))
>>> words
['xanadu', 'xyz', '', 'aardvark', 'apple', 'mix']

唯一的缺点是你正在改变给定的对象。这可以通过预先切片列表来解决。

>>> words = ['mix', 'xyz', '', 'apple', 'xanadu', 'aardvark']
>>> new_words = words[:]
>>> new_words.sort(key=lambda x: (not x.startswith('x'), x))
>>> new_words
['xanadu', 'xyz', '', 'aardvark', 'apple', 'mix']
>>> words
['mix', 'xyz', '', 'apple', 'xanadu', 'aardvark']

答案 4 :(得分:2)

words = ['xoo', 'dsd', 'xdd']
list1=filter(lambda word:word[0]=='x',words)
list2=filter(lambda word:word[0]!='x',words)

答案 5 :(得分:2)

重新发送变体SilenGhosts代码(随意复制,SilentGhost)作为代码而不是命令提示符日志

notinorder = ['mix', 'xyz', '', 'apple', 'xanadu', 'aardvark']
print sorted(notinorder, key = lambda x: (not x.startswith('x'), x))

答案 6 :(得分:1)

>>> x = ['abc', 'xyz', 'bcd', 'xabc']
>>> y = [ele for ele in x if ele.startswith('x')]
>>> y
['xyz', 'xabc']
>>> z = [ele for ele in x if not ele.startswith('x')]
>>> z
['abc', 'bcd']

答案 7 :(得分:0)

更多原始解决方案:

l1=[]
l2=[]
for w in sorted(words):
    (l1 if w[0] == 'x' else l2).append(w)
l1.extend(l2)
return l1