J. doe
J. doe

Reputation: 45

Tuple (key, value) to dictionary ValueError: dictionary update sequence element #0 has length 6; 2 is required

I have a string that I regex which returns me a tuple (see results printed) and I want to create a dictionary from it (first entry of tuple is key, second is value), which according to StackOverflow posts should work like a charm. The for loop can return multiple points which each should be added to a single dict that should be returned.

Code & Error:

import re as re

n = nuke.selectedNode()
k = n.knob('scene')
script = k.toScript().replace('\n','').split('scenegraph {')

for sgrph in script:
    for m in [re.match(r".*\bname '([Point\d]+)'.*\btransform ([0-9.e+\- ]+)",sgrph)]:
        if m is not None:
            print m.groups()
            items = dict(m.groups()) #this causes the error
            print "........."
print items

Output:

# Result: ('Point1', '1.983990908e+00 0.000000000e+00 0.000000000e+00 0.000000000e+00 0.000000000e+00 1.983990908e+00 0.000000000e+00 0.000000000e+00 0.000000000e+00 0.000000000e+00 1.983990908e+00 0.000000000e+00 5.610483289e-01 6.365304199e+03 4.553408813e+02 1.000000000e+00      ')
    Traceback (most recent call last):
      File "<string>", line 11, in <module>
    ValueError: dictionary update sequence element #0 has length 6; 2 is required

Upvotes: 3

Views: 225

Answers (2)

Ivan Velichko
Ivan Velichko

Reputation: 6709

Dict in python can be created from the iterable of (key, value) pairs. But you have a flat tuple of values as a result of m.groups() call. You need to pick even elements of this tuple as keys and then odd elements as corresponding values and then zip them together:

values = ('foo', 'bar', 'qux', 'blah')
dict(zip(values[::2], values[1::2]))

Here is an example using re.match().groups():

import re
match = re.match(r'(\d+) (\d+) (\d+) (\d+)', '12 34 56 78')
groups = match.groups()               # gives ('12', '34', '56', '78')
dict(zip(groups[::2], groups[1::2]))  # gives {'56': '78', '12': '34'}

UPD: Be aware that zip produces the sequence with the length truncated to the shortest length of its input. So if m.groups() returned odd number of elements the last value will not occur in the resulting dict.

Upvotes: 0

jpp
jpp

Reputation: 164773

In my opinion, it's a good idea to be explicit. For example, you can define your dictionary before your nested for loops, unpack explicitly and add an item to your dictionary.

res = {}

for sgrph in script:
    for m in [re.match(r".*\bname '([Point\d]+)'.*\btransform ([0-9.e+\- ]+)",sgrph)]:
        if m is not None:
            key, value = m.groups()
            res[key] = value

Upvotes: 1

Related Questions