2

一个例子:我有一个列表[1,2,3,4,5,6,7,8],我需要将它“拉伸”到 20,现有值尽可能均匀分布,“缺失”值替换为None,结果列表必须以 1 开头并以 8 结尾。

原始列表中的值和要分配的 20-8 个 None 值之间有 8-1 个空格,因此我们可以在每个“空格”中放置一个 None。

[1, None, 2, None, 3, None, 4, None, 5, None, 6, None, 7, None, 8]

现在我们还有 12-7None个值要分配,我们可以将其中的 4 个分配到其他空间:

[1, None, None, 2, None, 3, None, None, 4, None, 5, None,None 6, None, 7, None,
    None, 8]

现在我们剩下一个可以随机分配:

[1, None, None, 2, None, 3, None, None, 4, None, 5, None, None, 6, None, None 7, 
    None, None, 8]

有没有一种算法可以让你完成这样的任务?也许是一个实现?

4

3 回答 3

8

基本思想:只是从旧位置线性插入新位置。为简单起见,我们使用地板除法,但您可以更聪明地使用四舍五入除法以获得更均匀的分布。

def stretch_to(l, n):
    out = [None] * n
    m = len(l)
    for i, x in enumerate(l):
        out[i*(n-1)//(m-1)] = x

    return out

样本:

>>> stretch_to(range(8), 20)
[0, None, 1, None, None, 2, None, None, 3, None, 4, None, None, 5, None, None, 6, None, None, 7]
于 2012-10-20T19:44:14.467 回答
4

如果您的第一个列表中有 n 次,第二个列表中有 m 个项目。像这样的东西会起作用。

l2 = [None for I in range(m)]
for i, x in emumerate(l1):
    index = i * m / n
    l2[index] = l1[i]

您需要决定边缘情况的行为,如果m<n,该怎么办等。

于 2012-10-20T19:42:54.220 回答
1

这是我认为有趣的简洁替代方案:

def stretch(seq, n):
    seq = [seq[i * (len(seq) - 1) // (n - 1)] for i in range(n)]
    return [seq[0]] + [x if x != y else None for x, y in zip(seq[1:], seq)]

基于此,一个基于 itertools 的版本不会复制列表,返回一个迭代器,您可以选择将其转换为列表:

from itertools import tee, chain, izip
def stretch(seq, n):
    s1, s2 = tee(seq[i * (len(seq) - 1) // (n - 1)] for i in range(n))
    return chain((next(s1),), (x if x != y else None for x, y in izip(s1, s2)))
于 2012-10-21T00:07:08.920 回答