Home > OS >  dictionary conversion from reading files in python
dictionary conversion from reading files in python

Time:04-18

What is the difference between line number 5 and line number 6? line number 5 throws error but line number 6 works. I am unable to understand the difference.

 with open("file1.txt") as f:
    lines = f.readlines()
    
for line in lines:
    print(line)
    print(dict(line.split('=', 1))) # Line 5 throwing ValueError: dictionary update sequence element #0 has length 1; 2 is required


    
print(dict(line.split('=', 1) for line in lines)) # Line 6 works fine

CodePudding user response:

Suppose that we have values like the following for lines:

lines = ["foo=bar", "baz=ola"]

In this code:

print(dict(line.split('=', 1) for line in lines))

the argument to dict is an iterable of lists of two elements, similar to:

>>> dict([["foo", "bar"], ["baz", "ola"]])
{'foo': 'bar', 'baz': 'ola'}

In this code:

for line in lines:
    print(dict(line.split('=', 1)))

we call dict() multiple times, each time with a list of two elements, similar to:

>>> dict(["foo", "bar"])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: dictionary update sequence element #0 has length 3; 2 is required

"Dictionary update sequence element #0" is "foo"; each "sequence element" is a key, value pair, so the error is happening because dict() is trying to interpret "foo" as if it were a pair. Since your error message indicates "length 1", I'm guessing your file has a one-character name in it that is similarly being interpreted as a pair.

If we used two-character strings, it would "work", but it would work by using the first character as the key and the second character as the value:

>>> line = "ab=xy"
>>> dict(line.split("="))
{'a': 'b', 'x': 'y'}

The key takeaway is that the argument to dict must be all the key, value pairs, not a single key, value pair -- i.e. it must be a generator, list, or other iterable that contains other iterables with exactly two elements each. Even if you only have a single pair, you must put that pair inside an iterable (e.g. a list), because dict() will always treat its argument as an iterable of pairs.

CodePudding user response:

Here is the answer:

If no positional argument is given, an empty dictionary is created. If a positional argument is given and it is a mapping object, a dictionary is created with the same key-value pairs as the mapping object. Otherwise, the positional argument must be an iterable object. Each item in the iterable must itself be an iterable with exactly two objects. The first object of each item becomes a key in the new dictionary, and the second object the corresponding value.

In line 6 you have an iterator whose items are an iterable with two objects. Line 5 is just a list with two items.

CodePudding user response:

For a file like:

x=1
y=2
z=3

Use something like the following:

with open('f.txt') as f:
    lines = f.read().splitlines()  # strips newlines

new_dict = dict([line.split('=') for line in lines])

The list comprehension inside the call to dict produces a list where each element of the list are the split components of the lines. In this case:

[['x', '1'], ['y', '2'], ['z', '3']]

The dict function consumes iterables like this (with elements consisting of 2 elements) as key-value pairs.

If you inspect new_dict you'd see:

print(new_dict)
{'x': '1', 'y': '2', 'z': '3'}
  • Related