题目背景:
对给定的iterable进行排序,使其元素以递减的频率顺序结束,即它们在元素中出现的次数。如果两个元素具有相同的频率,它们应该以与iterable中第一次出现相同的顺序结束。(意思就是给你一个列表,对里面的元素按其出现个数进行排序,个数多的排前面;若个数相等,则按原列表里面该元素之间的位置关系保持不变进行排序,我把这类题型归结为根据列表元素数量排序,频率相等则按原位置顺序排)
这个是变式:Frequency Sorting(根据列表元素数量排序,频率相等则按自然顺序排)
Example:
frequency_sort([4, 6, 2, 2, 6, 4, 4, 4]) == [4, 4, 4, 4, 6, 6, 2, 2]
frequency_sort(['bob', 'bob', 'carl', 'alex', 'bob']) == ['bob', 'bob', 'bob', 'carl', 'alex']
代码实现:
def frequency_sort(items):
# your code here
dicts={i:items.count(i) for i in items}
dicts=dict(sorted(dicts.items(),key=lambda x:x[1],reverse=True))
lists=[]
for i in dicts:
for j in range(dicts[i]):
lists.append(i)
return lists
if __name__ == '__main__':
print("Example:")
print(frequency_sort([4, 6, 2, 2, 6, 4, 4, 4]))
# These "asserts" are used for self-checking and not for an auto-testing
assert list(frequency_sort([4, 6, 2, 2, 6, 4, 4, 4])) == [4, 4, 4, 4, 6, 6, 2, 2]
assert list(frequency_sort(['bob', 'bob', 'carl', 'alex', 'bob'])) == ['bob', 'bob', 'bob', 'carl', 'alex']
assert list(frequency_sort([17, 99, 42])) == [17, 99, 42]
assert list(frequency_sort([])) == []
assert list(frequency_sort([1])) == [1]
print("Coding complete? Click 'Check' to earn cool rewards!")
思路分析:
既然是按列表元素的出现频率进行排序,那就先要用count方法统计出元素的对应个数,利用字典来构建{元素:个数}这样的中间体,因字典的性质,重复判断的元素会被覆盖,所有不需要考虑重复计算问题而去用set集合。接着对字典里面的元素,按他的值的大小排序,这里需要用到sorted方法和dict.items,进而用匿名函数lambda找到个数,设置Reverse=True从大到小排序,最后再转化为dict类型。排序完了以后,就是完成题目的要求了,创建一个列表lists,双重循环法,最外层是字典的循环,目的是找到对应的元素,最内层是range对应的个数循环,目的是往列表里面添加相对应的元素个数,最后返回lists即可。
Best Code:
def frequency_sort(items):
return sorted(items, key=lambda x: (-items.count(x), items.index(x)))
print(frequency_sort([3, 4, 11, 13, 11, 4, 4, 7, 3]))