【问题标题】:Python: Unpacking arrays of tuples or of arrays - unpacking more than 2 elements per array or tuplePython:解包元组或数组的数组 - 每个数组或元组解包超过 2 个元素
【发布时间】:2018-04-18 09:26:07
【问题描述】:

我的目标是为更长的元组或更长的列表更优雅地解包子元组或子列表。

例如,我有一个带有子数组的数组

s = [['yellow', 1,5,6], ['blue', 2,8,3], ['yellow', 3,4,7], ['blue',4,9,1], ['red', 1,8,2,11]]

用 2 个元素的数组和子元组或子列表进行实验,我有以下内容:

s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]

s = [['yellow', 1], ['blue', 2], ['yellow', 3], ['blue', 4], ['red', 1]]

无论是元组还是列表,我都可以解压 's':

for k, v in s:
     print('k = {0}, v = {1}'.format(k,v))

产生结果

k = yellow, v = 1
k = blue, v = 2
k = yellow, v = 3
k = blue, v = 4
k = red, v = 1

假设我有以下数组,每个子数组包含四个元素:

bongo =   
[[1, 2, 3, 4], [6, 3, 2, 3], [5, 7, 11, 15], [2, 4, 7, 8]]

我可以使用变量 a、b、c、d 解压“bongo”

for a,b,c,d in bongo:
    print('a = {0}, b = {1}, c={2}, d={3}'.format(a,b,c,d))

a = 1, b = 2, c=3, d=4
a = 6, b = 3, c=2, d=3
a = 5, b = 7, c=11, d=15
a = 2, b = 4, c=7, d=8

尽管能够解压缩混合的 chr/数字子数组,但我似乎在解压缩混合的“chr”和数字子列表(或子元组(未显示,但得到相同的结果))时遇到问题:

s = [['yellow', 1,5,6], ['blue', 2,8,3], ['yellow', 3,4,7], ['blue',     
      4,9,1], ['red', 1,8,2,11]]

也就是说,在进行解包时,我得到了想要的结果,但出现了错误:

for a,b,c,d in s:
    print('a = {0}, b = {1}, c = {2}, d = {3} '.format(a,b,c,d))

a = yellow, b = 1, c = 5, d = 6 
a = blue, b = 2, c = 8, d = 3 
a = yellow, b = 3, c = 4, d = 7 
a = blue, b = 4, c = 9, d = 1 
Traceback (most recent call last):
  File "<pyshell#288>", line 1, in <module>
    for a,b,c,d in s:
ValueError: too many values to unpack (expected 4)

我的问题:有没有更优雅的解包方式,比如我想得到第一个元素,比如键,然后剩下的?

伪代码来说明——它不能直接在python中工作:

for k[0][0], v[0][1:4] in s:
     print('k[0][0] = {0},  v[0][1:4] = {1}'.format(k[0][0],v[0][1:4]))

如得到如下输出:

a = yellow, b = 1, c = 5, d = 6 
a = blue, b = 2, c = 8, d = 3 
a = yellow, b = 3, c = 4, d = 7 
a = blue, b = 4, c = 9, d = 1 

灵感: 尝试使用第 3.4.1 段 https://docs.python.org/3/library/collections.html#collections.defaultdict 的 defaultdict,特别是使用子元组解包数组。

谢谢, 悉尼的安东尼

【问题讨论】:

    标签: python arrays list dictionary tuples


    【解决方案1】:

    你可以先转换成你想要的格式:

    >>> ss = {x[0]: x[1:] for x in s}
    >>> ss
    {'blue': [4, 9, 1], 'red': [1, 8, 2, 11], 'yellow': [3, 4, 7]}
    >>> for s, v in ss.items():
    ...     print "a = {0} b = {1} c = {2} d = {3}".format(s, *v)
    ...
    a = blue b = 4 c = 9 d = 1
    a = red b = 1 c = 8 d = 2
    a = yellow b = 3 c = 4 d = 7
    >>>
    

    【讨论】:

    • 效果很好,非常感谢。限制是你不能有一个重复的键,比如两个 'red' 。此外,与键关联的列表/数组/元组必须与字典中的其他列表/数组/元组长度相同。尽管如此,这正是我想要的。问候,悉尼的安东尼
    • 确实如此。我没有意识到那把钥匙不是独一无二的。我喜欢你下面的解决方案。
    【解决方案2】:

    在 Azim 先生的回答中,他在第 5 行使用了 *v。这启发了我将其应用于数组/元组/列表而不是字典的进一步实验。

    此代码产生相同的结果:

    s = [('yellow', 1, 5, 6), ('blue', 2, 8, 3), ('green', 4, 9, 1), ('red', 1, 8, 2)]
    
    for x, *y in s:
        temparray = [b for b in y]; Note we don't use *y
        print('x = {0}, temparray = {1}'.format(x, temparray))
    

    作为

    for x, *y in s:
        print('x = {0}, y = {1}'.format(x,y)); note we don't use *y
    
       x = yellow, y = [1, 5, 6]
       x = blue, y = [2, 8, 3]
       x = green, y = [4, 9, 1]
       x = red, y = [1, 8, 2]
    
    type(y)
       <class 'list'>  
    

    结论:*运算符不仅可以应用于字典,还可以应用于数组/元组/列表。在“for”循环中应用时,如

    for var1 *var2 in aListorTupleorArray:
         # var1 gets the first element of the list or tuple or array
         # *var2 gets the remaining elements of the list or tuple or array
         print('var1 = {0}, var2 = {1}'.format(var1,var2);#Note we don't use the * in *var2. just use var2
    

    谢谢, 令人兴奋的悉尼安东尼

    【讨论】:

    • 据你所知,我从 *args**kwargs 中得到了关于 *v 的想法,用于解包位置和键值函数参数。
    【解决方案3】:

    这里是打印 *v 和 v 之间的细微差别。

    #printing v in the loop
    for s,v in ss.items():
          print("s = {0}, v = {1}".format(s,v)); #printing s & v 
    
    s =  yellow, v = [3,4,7]
    s =  blue,  v = [4,9,1]
    s =  red,  v = [1,8,2]
    

    然后我们有

    #printing *v in the loop
    for s,v in ss.items():
          print("s = {0}, *v = {1}".format(s,*v)); #printing s & *v 
    
    s =  yellow, v = 3 4 7
    s =  blue,  v = 4 9 1
    s =  red,  v = 1 8 2
    

    注意这里的微妙之处:无论我们在 'for' 循环中使用 *v,打印 v 还是 *v 都会产生相同的结果:

    #printing v in the loop
    for s,*v in ss.items():
          print("s = {0}, v = {1}".format(s,v)); #printing s & v 
    
    #printing v in the loop
    for s,*v in ss.items():
          print("s = {0}, v = {1}".format(s,*v)); #printing s & v 
    

    产生相同的结果:

    s =  yellow, v = [[3,4,7]]
    s =  blue,  v = [[4,9,1]]
    s =  red,  v = [[1,8,2]]
    

    谢谢你, 悉尼的安东尼

    【讨论】:

      猜你喜欢
      • 2021-12-20
      • 1970-01-01
      • 2015-05-15
      • 1970-01-01
      • 1970-01-01
      • 2021-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多