P114: Duplicate the elements of a list

重复列表中的每一个元素。照例还是先写测试用例:

from python99.lists.p114 import duplicate def test_duplicate(): assert duplicate([]) == [] assert duplicate([1]) == [1, 1] assert duplicate([1, 1, 2, 3]) == [1, 1, 1, 1, 2, 2, 3, 3]

这题用MapReduce范式来解会很清晰。MapReduce中的主要概念「Map(对映)」和「Reduce(归纳)」是从函数式程序设计语言借来的。简单来说,一个对映函数就是对列表上每一个元素进行指定的操作,并将结果存储于新的列表中。而归纳操作则是对一个列表的元素进行适当的合併。

本例中,map就是把单个元素对映成包含两个相同元素的列表,reduce则是把以上所有的列表都拼接成一个列表。举个例子,给定列表[1, 2, 3, 4]。首先,将列表中每一个元素都对映成包含两个相同元素的列表。然后,把所有的列表都拼接起来。

代码实现:

# Duplicate the elements of a list import functools import operator def duplicate(l): return functools.reduce(operator.concat, [[e] * 2 for e in l], [])

Python内建的List comprehension用一种简洁的方式实现了「Map(对映)」。标准库中的functools则提供了「Reduce(归纳)」的实现。

List comprehension的形式为:

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

本例中,f[x] * 2,将单个元素转换为包含两个相同元素的列表。

functools.reduce的源代码为:

_initial_missing = object()

def reduce(function, sequence, initial=_initial_missing):
    """
    reduce(function, sequence[, initial]) -> value
    Apply a function of two arguments cumulatively to the items of a sequence,
    from left to right, so as to reduce the sequence to a single value.
    For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
    ((((1+2)+3)+4)+5).  If initial is present, it is placed before the items
    of the sequence in the calculation, and serves as a default when the
    sequence is empty.
    """

    it = iter(sequence)

    if initial is _initial_missing:
        try:
            value = next(it)
        except StopIteration:
            raise TypeError("reduce() of empty sequence with no initial value") from None
    else:
        value = initial

    for element in it:
        value = function(value, element)

    return value

try:
    from _functools import reduce
except ImportError:
    pass

reduce返回值应与initial同类型。function接受两个参数,第一个应与initialreduce返回值同类型,第二个是sequence里的元素。

本例中,initial是空列表[]sequence的每个元素都是包含两个相同元素的列表。function接受的两个参数都是无嵌套的列表,并将它们拼接成一个无嵌套的列表。

results matching ""

    No results matching ""