Python中的列表扩展

3
一个例子:我有一个列表[1,2,3,4,5,6,7,8],我需要将其“拉伸”到长度20,现有值尽可能均匀地分布,“缺失”的值用None替换,结果列表必须以1开头并以8结尾。
原始列表中值之间有8-1个空格,而20-8个空值需要分配,因此我们可以将单个None放置在每个“空格”中。
[1, None, 2, None, 3, None, 4, None, 5, None, 6, None, 7, None, 8]

现在我们仍有12-7个“None”值需要分配,我们可以将其中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]

有没有一种算法可以完成这样的任务?或者有实现方式吗?

1
由于这不是标准问题,当然你不会得到任何预先设计的算法。你需要自己设计一个。 - Rohit Jain
2
看到您尝试解决这个问题也会很不错。 - Blender
3
这最后一个案例对我来说看起来不公平;“5”和“6”之间的差距太大了。 - nneonneo
请定义“尽可能均匀”;正如@nneonneo所说,您的示例似乎不太均匀。 - Scott Hunter
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]

4
如果你的第一个列表中有n个项目,第二个列表中有m个项目,可以尝试以下代码:

something like this will work.

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

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


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)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接