Mein Ziel ist es, ein Untertupel oder eine Unterliste für längere Tupel oder längere Listen eleganter auszupacken.

Zum Beispiel habe ich ein Array mit Sub-Arrays

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

Beim Experimentieren mit einem Array und einem Untertupel oder einer Unterliste mit 2 Elementen habe ich Folgendes:

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

ODER

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

Ich kann 's' auspacken, ob es Tupel oder Listen hat:

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

Erzeugt das Ergebnis

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

Angenommen, ich habe das folgende Array mit Unterarrays mit jeweils vier Elementen:

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

Ich kann 'Bongo' mit den Variablen a, b, c, d auspacken

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

Obwohl ich in der Lage bin, das gemischte chr / number-Subarray zu entpacken, habe ich anscheinend ein Problem beim Entpacken einer gemischten 'chr'- und number-Subliste (oder eines Subtupels (nicht gezeigt, aber mit dem gleichen Ergebnis)):

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

Das heißt, beim Auspacken erhalte ich das gewünschte Ergebnis mit einem Fehler:

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)

Meine Frage: Gibt es eine elegantere Art des Auspackens, so dass ich das erste Element, beispielsweise als Schlüssel, und den Rest erhalten möchte?

Zur Veranschaulichung mit Pseudocode funktioniert dies nicht direkt in 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]))

Um die folgende Ausgabe zu erhalten:

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 

Inspiration: Experimentieren mit dem Standarddikt in Abschnitt 3.4.1 https: //docs.python .org / 3 / library / collection.html # collection.defaultdict insbesondere das Entpacken eines Arrays mit einem Untertupel.

Vielen Dank, Anthony von Sydney

0
Anthony from Sydney 18 Apr. 2018 im 12:26

3 Antworten

Beste Antwort

Nach der Antwort von Herrn Azim verwendete er in der 5. Zeile * v. Dies hat mich dazu inspiriert, dies für weitere Experimente auf ein Array / Tupel / eine Liste anstelle des Wörterbuchs anzuwenden.

Dieser Code erzeugt das gleiche Ergebnis:

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

Wie

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

Fazit: Der Operator * kann nicht nur in Wörterbüchern, sondern auch in Arrays / Tupeln / Listen angewendet werden. Bei Anwendung in einer 'for'-Schleife wie in

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

Danke, Anthony von aufregendem Sydney

1
Anthony from Sydney 18 Apr. 2018 im 19:29

Hier ist ein subtiler Unterschied zwischen dem Drucken von * v und 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]

Dann haben wir

#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

Beachten Sie die Subtilität hier: Ob wir * v in der 'for'-Schleife verwenden, print v oder * v ergibt das gleiche Ergebnis:

#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 

Erzeugt das gleiche Ergebnis:

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

Vielen Dank, Anthony von Sydney

0
Anthony from Sydney 20 Apr. 2018 im 08:22

Sie können zuerst in das gewünschte Format konvertieren:

>>> 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
>>>
1
Mohammad Azim 18 Apr. 2018 im 09:32