I am trying to convert "Random = 1" into dictionary {"Random":1} I tried
Key = (line.split('=')[0]).split()[0] #to get key and remove spaces
value = (line.split('=')[1]).split()[0]
CQ_Options[Key] = value
How could I do it in more mature way?
4 Answers 4
First off, you should standardize your names, Key
and value
don't follow the same naming rules, or if they do, they're not apparent to me.
And so I'd recommend that you name your things in lower_snake_case
, to adhere to PEP8.
After this I'd use str.strip
rather than str.split
.
And use a list comprehension to change both the key and value without having to duplicate the code, which can remove the key
and value
variables altogether.
This can leave you with:
item = [i.strip() for i in line.split('=')]
CQ_options[item[0]] = item[1]
If you want to stick with using key
and value
however, you need to make sure that line.split('=')
will only return two items. You can make sure it'll return a max of two items with the optional parameter, and since we'd already error if there's not at least a single =
, then you can use:
key, value = [i.strip() for i in line.split('=', 1)]
CQ_options[key] = value
You can use a dict comprehension if you have multiple items in a list, for example:
a = ["Random = 1", "Ran = 3"]
print {k.strip(): int(v.strip()) for k, v in (i.split("=") for i in a)}
>>> {'Ran': 3, 'Random': 1}
If you want to update an existing dictionary d
:
d.update({k.strip(): int(v.strip()) for k, v in (i.split("=") for i in a)})
-
\$\begingroup\$ Sorry I changed my answer completely, the first one was no very helpful! \$\endgroup\$kezzos– kezzos2017年04月10日 12:51:46 +00:00Commented Apr 10, 2017 at 12:51
-
\$\begingroup\$ This answer shows how to use a dict comprehension \$\endgroup\$kezzos– kezzos2017年04月10日 15:08:30 +00:00Commented Apr 10, 2017 at 15:08
-
\$\begingroup\$
print {k.strip(): int(v.strip()) for k, v in [line.split("=")]}
would be the way to split the OP one-line data source. But that's only a few characters shorter than just explicitly doing the also-confusingprint {line.split("=")[0].strip() : int(line.split("=")[-1].strip())}
--all that to say, I don't think dict comprehension is a good fit here. \$\endgroup\$MarkHu– MarkHu2017年04月10日 22:19:28 +00:00Commented Apr 10, 2017 at 22:19
Another naive approach would be to take advantage of the fact that default split()
uses whitespace, and discard the =
delimiter.
line = "Random = 1"
my_dict = { line.split()[0] : line.split()[2]}
Note that the un-used value of line.split()[1]
is =
in this case, but could be :
or anything. But this is naive in that it requires spaces.
A little better:
import re
line = "Random= 1"
my_dict = { re.split(' |=',line)[0] : re.split(' |=',line)[-1] }
Both examples yield {'Random': '1'}
but the latter is more flexible.
But better yet, try a standard lib like configparser which has other nice features like ignoring comment lines.
If you have one key-value pair per line, and you just want to parse all lines and transform them into a dictionary:
import re
...
CQ_Options = dict(re.split(r'\s*=\s*', line, 1) for line in text.splitlines())
I don't know if you're familiar with regular expressions or Python in general so I'll explain.
This will:
- First split
text
into lines and remove newline characters. Thesplitlines
method will take care of\r
akaCR
on Windows. - Then each line is split by the regular expression
\s*=\s*
:\s
is whitespace, such as spaces and tabs*
is zero or more repetitions of the previous expression, in this case zero or more whitespace characters- the argument
1
means it will only split at the first occurrence, not all occurrences - so the line is split by the first equals sign preceded and followed by an arbitrary amount of spaces, tabs, etc.
- Then you have a sequence of key-value pairs.
- These will be converted into a dictionary using the
dict
constructor, which given a sequence of key-value pairs converts them into a dictionary.
EDIT
@Peilonrayz has pointed out that this will not strip whitespace on the outer side of the key-value pair. For example " key = value "
will become {' key': 'value '}
. I originally assumed whitespace would be only between the key, equals sign, and value.
To remove whitespace on both sides of key and value:
CQ_Options = dict(
map(str.strip, line.split('=', maxsplit=1))
for line in text.splitlines()
)
-
\$\begingroup\$ This doesn't remove white space around each key and value.
' abc = def '
will become{' abc': 'def '}
. Also obligatory XKCD. \$\endgroup\$2017年04月10日 10:35:42 +00:00Commented Apr 10, 2017 at 10:35 -
\$\begingroup\$ Come on. Don't tell me you don't ever find RE useful. You're right about the whitespace but guess what, it can be solved by using regular expressions. Actually the whole thing can be done using a single
finditer
. \$\endgroup\$kyrill– kyrill2017年04月10日 10:38:47 +00:00Commented Apr 10, 2017 at 10:38 -
1\$\begingroup\$ Yes I do find them useful, here maybe they're overkill, and over-reliance leads to problems. \$\endgroup\$2017年04月10日 10:41:31 +00:00Commented Apr 10, 2017 at 10:41
-
1\$\begingroup\$ @Peilonrayz Well, there's another XKCD :-P \$\endgroup\$ChatterOne– ChatterOne2017年04月10日 10:54:54 +00:00Commented Apr 10, 2017 at 10:54
-
1\$\begingroup\$
*
actually means 0 or more,+
means 1 or more repetitions. \$\endgroup\$Tamoghna Chowdhury– Tamoghna Chowdhury2017年04月10日 13:08:37 +00:00Commented Apr 10, 2017 at 13:08
ConfigParser
lib \$\endgroup\$=
), it is better to use a standard lib. Other benefits in this case, include ignoring comment lines. The only time home-grown one-offs are both safe & easy is when the input is also controlled by you (i.e. a companion microservice passing URL args.) \$\endgroup\$pyparsing
. \$\endgroup\$