Python 包含任何类型项的列表的总和

Python 包含任何类型项的列表的总和,python,list,Python,List,我正在学习python,我们的老师告诉我们写一个函数,它将返回列表的和,不管它的值是什么类型的 如果列表是整数,则:sum([1,4,5,6])=16 如果列表是字符串,那么:sum(['a','b',c'])='abc' 列表也可以由元组和其中的列表组成 代码需要尽可能简短。我试着写下: element = list[0] for thing in list: for thingy in thing: element += thingy print element 但

我正在学习python,我们的老师告诉我们写一个函数,它将返回列表的和,不管它的值是什么类型的

如果列表是整数,则:
sum([1,4,5,6])=16

如果列表是字符串,那么:
sum(['a','b',c'])='abc'

列表也可以由元组和其中的列表组成

代码需要尽可能简短。我试着写下:

element = list[0]
for thing in list:
    for thingy in thing:
        element += thingy
print element

但是它不起作用。。你知道怎么做吗?

你可以使用
reduce
,而不是内置的
sum
,它需要在整个列表或元组中使用整数或浮点数:

s1 = [1, 4, 5, 6]
s2 = ['a', 'b', 'c']
print(reduce(lambda x, y:x+y, s1))
print(reduce(lambda x, y:x+y, s2))
from functools import reduce
print(reduce(lambda x, y:x+y, s1))
输出:

16
abc
abcdeh18ddb
在Python3中,
functools
必须使用
reduce

s1 = [1, 4, 5, 6]
s2 = ['a', 'b', 'c']
print(reduce(lambda x, y:x+y, s1))
print(reduce(lambda x, y:x+y, s2))
from functools import reduce
print(reduce(lambda x, y:x+y, s1))
编辑:要对嵌套列表的值求和,最好使用递归,因为列表可以具有任意深度:

def flatten(l):
   return reduce(lambda x, y:x+y, [i if not isinstance(i, list) else flatten(i) for i in l])

print(flatten([['a', 'b', 'c'], ['d', 'e', ['h', ['18', 'dd', 'b']]]]))
输出:

16
abc
abcdeh18ddb

您的代码无法工作,因为您将第一个元素连接/求和两次

示例:-
让我们假设
listy=[1,2,3,4,5]

&
element=listy[0]=1

现在开始第一次迭代
element=element+thingy(1+1)
,因为第一次迭代的thingy也指向
listy[0]

只需检查列表中元素的类型:-

例如

if isinstance(string, list[0]) :
    sum = ""
elif isinstance(int, list[0]):
    sum = 0
else :
    // raise some error
for i in listy:
    sum += i

首先,我应该指出您将
元素初始化为
列表[0]
的错误。。。您将添加两次

所以,要解决这个问题,我的第一反应是从-

def generic_sum(data):
    return sum(data, type(data[0])())
但这仅适用于整数和浮点数、列表和元组以及
计数器
对象(字符串也有
\uuuuuuuuuuu添加
方法,但它们是
求和
特殊情况)

因此,我们需要一个更通用的解决方案,它应该适用于任何类型的数据


这里有一个,但是您需要注意列表元素可以任意嵌套。我的方法是首先将数据展平,然后对其元素求和

幼稚的做法是——

flat_data = [y for x in data for y in (x if isinstance(x, list) else [x])]
您也可以这样写:

flat_data = []
for x in data:
    if not isinstance(x, list):
        x = [x]
    flat_data.extend(x)
然后呢,

init = flat_data[0]
for v in flat_data[1:]:
    init += v
将其放入函数中,您有-

def generic_sum(data):
    flat_data = [y for x in data for y in (x if isinstance(x, list) else [x])]

    sum_ = flat_data[0]   # don't use `sum`, you hide the builtin that way
    for v in flat_data[1:]:
        sum_ += v

    return sum_  
下面是一些示例输入的演示-


如果你想提高效率,我建议你做两件事-

  • 对数值使用
    sum
    ,而不是使用循环手动相加,然后
  • 特殊套管柱,通过对其调用
    str.join
    ,而不是求和
  • 它的工作原理与上面相同,但是对于字符串连接应该更有效

    注意

    • 对于python2,使用
      isinstance(flat_data[0],basestring)
      (因为可以使用
      str
      unicode
      对象)

    • 调用
      str.join
      在计算上比求每个字符的和(二次时间)便宜(线性时间)。这是字符串不可变这一事实的结果


    基准

    data = ['a', 'b', ['c', 'd']] * 1000000
    

    在处理数百万个元素时,这两种方法都会跨越一秒钟。我认为这是因为变平的步骤。或者,让我们在平面数据上计算求和代码的时间

    flat_data = ['a', 'b', 'c', 'd'] * 1000000
    

    这更有意义,并且更好地表明在循环中串联字符串的效率低下

    此外,
    generic\u sum\u opt
    对数字求和更快

    data = [[1], 2, 3, [4, 5, 6]] * 1000000
    


    由于在那里使用了
    sum
    ,第二个函数肯定更快

    为什么不起作用?对于数字,错误是:“int”对象不可iterable,对于字符串,字符串的第一个元素有两次。对于元组和列表,我得到了更多的错误,只需对列表中的东西执行:
    :element+=thing
    。为什么是第二个循环?@cᴏʟᴅsᴘᴇᴇᴅ 因为列表中可能有一个列表。我还需要对内部列表中的所有值求和,不要将
    list
    用作变量名<代码>列表()
    是一个,您可以用脚本覆盖它。告诉你的老师,他/她应该教你蟒蛇。谢谢,我不知道这个功能。对于内部列表和元组会这样吗?@eitanmayer假设嵌套列表是
    ['a','b','c'],['d','e','f']
    。您希望从该列表中得到什么<代码>['abc','def']或
    'abcdef'
    ?abcdef-函数应包含所有内容one@coldspeed为什么(四元时间)@MukulSharma每次你向另一个字符串添加一个字符串时,你必须分配新的内存,这是线性的,而且是浪费的。执行线性运算的次数是线性的,因此它是二次的。@MukulSharma字符串串联每次都需要创建一个全新的字符串。@coldspeed and how join avoidthat@MukulSharma自从您提出要求以来,我们已经为该功能投入了大量的工作,以优化其效率。问题的关键在于,内存只分配一次,而且是线性的(尽管细节有点不确定)。本问答提供了一个良好的视角:
    %timeit generic_sum_opt(data)
    1 loop, best of 3: 1.21 s per loop
    
    flat_data = ['a', 'b', 'c', 'd'] * 1000000
    
    %%timeit
    sum_ = flat_data[0]   # don't use `sum`, you hide the builtin that way
    for v in flat_data[1:]:
         sum_ += v
    
    1 loop, best of 3: 623 ms per loop
    
    %timeit ''.join(flat_data)
    10 loops, best of 3: 35.5 ms per loop
    
    data = [[1], 2, 3, [4, 5, 6]] * 1000000
    
    %timeit generic_sum(data)
    1 loop, best of 3: 1.94 s per loop
    
    %timeit generic_sum_opt(data)
    1 loop, best of 3: 1.53 s per loop