【问题标题】:Adding elements between elements in list在列表中的元素之间添加元素
【发布时间】:2017-08-05 13:00:25
【问题描述】:

如果我有一个列表,例如。

[1,2,3]

还有一个函数 f(),我如何插入这样的新列表:

[1, f(1), 2, f(2), 3, f(3)]? 

【问题讨论】:

标签: python list


【解决方案1】:

你可以使用:

[y for x in data for y in (x,f(x))]

data 是初始列表,f 当然是你要应用的功能。

例如,如果fstr 函数(将数字转换为其文本等价物),它将生成:

>>> data = [1,2,3]
>>> f = str
>>> [y for x in data for y in (x,f(x))]
[1, '1', 2, '2', 3, '3']

所以这里我们得到[1, '1', 2, '2', 3, '3'],其中1是初始1'1'f(1)

基准测试:我将following test setup 更改为:

import pandas as pd
from timeit import timeit
from itertools import chain

wvo = lambda d, f: [y for x in d for y in (x,f(x))]
max = lambda d, f: list(chain.from_iterable(zip(d, map(f, d))))
mrc = lambda d, f: sum([[x,f(x)] for x in d], [])
chi = lambda d,f: [j for k in map(lambda x: (x, f(x)), d) for j in k]
mar = lambda d,f: [ee for e in zip (d, map (f, d)) for ee in e]

results = pd.DataFrame(
    index=pd.Index([1, 3, 10, 30, 100, 300,
                    1000, 3000, 10000, 30000, 100000], name='N'),
    columns='wvo max mrc chi mar'.split(),
    dtype=float
)

for i in results.index:
    pd.concat([df] * i, ignore_index=True)
    d = list(range(i))
    f = str
    for j in results.columns:
        stmt = '{}(d,f)'.format(j)
        setp = 'from __main__ import d, f, {}'.format(j)
        results.set_value(i, j, timeit(stmt, setp, number=10))

这意味着我们可以使用 pandas 测试不同文件大小的不同答案。对于每个配置,我们使用 timeit 执行 10 次测试。

这会生成以下时间(以秒为单位):

             wvo       max          mrc       chi       mar
N                                                          
1       0.000016  0.000029     0.000018  0.000022  0.000020
3       0.000026  0.000029     0.000031  0.000034  0.000026
10      0.000057  0.000053     0.000061  0.000076  0.000062
30      0.000145  0.000122     0.000210  0.000200  0.000145
100     0.000440  0.000347     0.000899  0.000588  0.000407
300     0.001263  0.000637     0.004416  0.001721  0.000680
1000    0.002425  0.001897     0.040877  0.003796  0.002325
3000    0.009269  0.009798     0.289162  0.015486  0.008430
10000   0.037131  0.032563     3.823171  0.044008  0.030609
30000   0.078577  0.060828    53.803486  0.096703  0.066899
100000  0.255477  0.195669  1094.482380  0.289030  0.191143

或者相对而言(最好是1.00):

         wvo   max      mrc   chi   mar Best
N                                           
1       1.00  1.78     1.11  1.36  1.19  wvo
3       1.03  1.15     1.23  1.32  1.00  mar
10      1.08  1.00     1.17  1.45  1.18  max
30      1.19  1.00     1.73  1.65  1.20  max
100     1.27  1.00     2.59  1.69  1.17  max
300     1.98  1.00     6.93  2.70  1.07  max
1000    1.28  1.00    21.55  2.00  1.23  max
3000    1.10  1.16    34.30  1.84  1.00  mar
10000   1.21  1.06   124.90  1.44  1.00  mar
30000   1.29  1.00   884.52  1.59  1.10  max
100000  1.34  1.02  5725.98  1.51  1.00  mar

【讨论】:

    【解决方案2】:
    In [18]: lst = [1,2,3]
    
    In [19]: def f(x):
        ...:     return x**2
        ...:
    
    In [20]: from itertools import chain
    
    In [21]: list(chain.from_iterable(zip(lst, map(f, lst))))
    Out[21]: [1, 1, 2, 4, 3, 9]
    

    【讨论】:

      【解决方案3】:

      与威廉的回答略有不同的方法,避免了两个循环:

      sum([[x,f(x)] for x in my_list], [])
      
      • [x, f(x)] 创建一个包含两个元素的列表,其中包含当前元素和应用于它的函数。

      • sum(..., []) 将列表展平。

      【讨论】:

      • 对,因为sum不用循环就可以工作,而且重复的列表串联效率更高……这样就差很多了;有一个循环并不是一件坏事。
      • 没有dv(did +1),但不是因为你没有看到循环,所以没有循环。切片或扩展在内部使用循环...我唯一的问题是 Python 是否使用 __add____iadd__ 因为在前一种情况下,这将导致 O(n^2)算法。
      • 基于快速实验,初始值[]没有更新。所以这可能意味着它使用__add__。这个question 证实了这一点。
      • sum 应该用于可迭代对象。这是非常低效的。甚至the documentation 也明确指出应该改用itertools.chain
      • 我同意这具有O(n^2) 的复杂性,并且有两个循环完全不是一件坏事,但我不同意这样的效率低得多。对这两种方法进行测试导致每种情况下的时间相当。尽管它不是最可行的解决方案,但内部方法的效率远低于顶级循环的说法是不正确的。此外,考虑到他们提供的测试,我真的怀疑 OP 是否需要一种非常高效的方法。
      【解决方案4】:
      >>> data = [1, 2, 3]
      >>> f = lambda x : x + 1
      >>> [ee for e in zip (data, map (f, data)) for ee in e]
      [1, 2, 2, 3, 3, 4]
      

      【讨论】:

        【解决方案5】:

        您可以使用maplist comprehension

        f = lambda x: x**3
        a = [1, 2, 3]
        output = [j for k in map(lambda x: (x, f(x)), a) for j in k]
        print(output)
        

        输出:

        [1, 1, 2, 8, 3, 27]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-01-24
          • 2017-11-30
          • 2022-10-04
          • 2018-10-03
          • 1970-01-01
          • 1970-01-01
          • 2020-08-12
          • 1970-01-01
          相关资源
          最近更新 更多