P128: Sorting a list of lists according to length of sublists

按照子列表长度排序包含列表的列表。本题要实现两种排序:按子列表长度排序和按子列表长度在全列表中的频率排序。

照例还是先写测试用例:

from python99.lists.p128 import lsort, ifsort def test_lsort(): assert lsort([[1, 2, 3], ['a', 'b'], [4]]) == [[4], ['a', 'b'], [1, 2, 3]] def test_ifsort(): assert ifsort([[1, 2, 3], [4, 5, 6], [7, 8, 9], ['a'], ['b'], ['c', 'd']]) == [ ['c', 'd'], ['a'], ['b'], [1, 2, 3], [4, 5, 6], [7, 8, 9]]

先解第一个「按子列表长度排序」。首先,将每个子列表转换成列表和长度组成的二元组。这个可以使用List Comprehension实现。 List comprehension的形式为:

[f(x) for x in l]
  • f为对映函数,其可为普通Python函数,也可为表达式
  • x为局部变量,用于引用每一个元素
  • l输入序列

本例中,f为二元组构造表达式(e, len(e))。 然后,使用内建的排序函数sorted排序。sorted可以通过lambda表达式自定义排序所基于的键。 最后,再把排好序的列表中的每一个二元组拆包,析出子列表。

代码实现:

# Sorting a list of lists according to length of sublists # a) We suppose that a list (Inlist) contains elements that are lists themselves. # The objective is to sort the elements of InList according to their length. # E.g. short lists first, longer lists later, or vice versa. import functools def lsort(l): return [l_and_length[0] for l_and_length in sorted([(e, len(e)) for e in l], key=lambda x: x[1])]

再解第二个「按子列表长度在全列表中的频率排序」。首先,把列表中的每一个元素「子列表」转换为「子列表和长度频率」二元组。这其中先读取子列表长度,再使用「字典(dictionary)」和「归纳(reduce)」统计长度频率,最后构造「子列表和长度频率」二元组。 然后,使用内建的排序函数sorted排序。 最后,把排好序的列表中的二元组拆包,析出子列表。

代码实现:

# b) Again, we suppose that a list (InList) contains elements that are lists themselves. # But this time the objective is to sort the elements of InList according to their length frequency; # i.e. in the default, where sorting is done ascendingly, lists with rare lengths are placed first, # others with a more frequent length come later. def ifsort(l): list_with_length = [(e, len(e)) for e in l] lengths = [e[1] for e in list_with_length] length_frequency = functools.reduce(accum_to_dict, lengths, {}) list_with_length_frequency = [ (e[0], length_frequency[e[1]]) for e in list_with_length] return [e[0] for e in sorted( list_with_length_frequency, key=lambda x: x[1])] def accum_to_dict(d, value): if value not in d: d[value] = 1 else: d[value] = d[value]+1 return d

results matching ""

    No results matching ""