Simple way to convert list to dict - python

Please, tell me the simplest way to convert list object to dictionary.
All parameters are looks like this:
['a=1', 'b=2', ...]
And I want to convert it into:
{'a': '1', 'b': '2' ...}

You could use:
>>> x
['a=1', 'b=2']
>>>
>>> dict( i.split('=') for i in x )
{'a': '1', 'b': '2'}
>>>

For each element in the list, split on the equal character, and add to dictionary using the resulting list from split.

Related

Values in python dictionary getting converted to double quotes rather than single quotes

I have a dictionary with the below values :-
test_dict = {'a': ['a1', 'a2'], 'b': ['1.1.1.1:1111', '2.2.2.2:2222', '3.3.3.3:3333,4.4.4.4:4444', '5.5.5.5:5555']}
I need to replace the comma (,) between 3.3.3.3:3333 and 4.4.4.4:4444 with (',) which is (single quote comma space) like that of the others.
I tried the code below but the output is coming with double quotes (")
val = ','
valnew = '\', \'' # using escape characters - all are single quotes
for k, v in test_dict.items():
for i, s in enumerate(v):
if val in s:
v[i] = s.replace(val, valnew)
print(test_dict)
Output:
{'a': ['a1', 'a2'], 'b': ['1.1.1.1:1111', '2.2.2.2:2222', "3.3.3.3:3333', '4.4.4.4:4444", '5.5.5.5:5555']}
Expected Output:
{'a': ['a1', 'a2'], 'b': ['1.1.1.1:1111', '2.2.2.2:2222', '3.3.3.3:3333', '4.4.4.4:4444', '5.5.5.5:5555']}
Please suggest.
print is displaying a representation of the dict, as if print(repr(test_dict)) was called.
[repr returns] a string containing a printable representation of an object. For many types, this function makes an attempt to return a string that would yield an object with the same value when passed to eval() ..
Since the value is a string which contains a ' it is using a " instead during the representation of the string. Example:
print(repr("helloworld")) # -> 'helloworld'
print(repr("hello'world")) # -> "hello'world"
This representation should generally only be used for diagnostic purposes. If needing to write this special format, the dict has to be walked and the values printed explicitly "per requirements".
If wishing for a reliable output/encoding with well-defined serialization rules, use a common format like JSON, XML, YAML, etc..
You're confusing data with representation. The single quotes, space, and comma ', ' are part of the representation of strings inside a list, not the string itself.
What you're actually trying to do is split a string on a comma, e.g.
>>> '3,4'.split(',')
['3', '4']
You can do this within a list by splitting and flattening, like this:
[s1 for s0 in v for s1 in s0.split(',')]
So:
>>> b = ['1', '2', '3,4', '5'] # Using simpler data for example
>>> b = [s1 for s0 in b for s1 in s0.split(',')]
>>> print(b)
['1', '2', '3', '4', '5']
'3.3.3.3:3333,4.4.4.4:4444' is a single string and the outer quote marks are just python's way of showing that. The same thing for "3.3.3.3:3333', '4.4.4.4:4444" - it is a single string. The outer double quotes are just python's way of showing you the string. The internal single quotes and comma are literally those characters in the string.
Your problem seems to be that some values in the list have been merged. Likely the problem is whatever wrote the list in the first place. We can fix it by splitting the strings and extending the list. List items that don't have embedded commas split to a single item list so extend into our new list as a single item. No change. But items with a comma split into a 2 item list and extend the new list by 2.
test_dict = {'a': ['a1', 'a2'], 'b': ['1.1.1.1:1111', '2.2.2.2:2222', '3.3.3.3:3333,4.4.4.4:4444', '5.5.5.5:5555']}
def list_expander(alist):
"""Return list where values with a comma are expanded"""
new_list = []
for value in alist:
new_list.extend(value.split(","))
return new_list
new_dict = {key:list_expander(val) for key, val in test_dict.items()}
print(new_dict)
The result is
{'a': ['a1', 'a2'], 'b': ['1.1.1.1:1111', '2.2.2.2:2222', '3.3.3.3:3333', '4.4.4.4:4444', '5.5.5.5:5555']}
Try something like this:
test_dict["b"] = ",".join(test_dict["b"]).split(",")
Updated:
import re
# do this once for the entire list
do_joinsplit_regex = re.compile(
r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,4}"
)
for d in sample_list:
for k,v in d.items():
if not isinstance(v, list) or len(v) < 1:
continue
d[k] = ",".join(v).split(",")

Replace item in list with one of several options given its contents

As in:
data = data.replace(['a', 'b', 'c'], [0, 1, 2])
Given 'a' replace with 0. Given 'b' replace with 1. Given 'c' replace with 2.
I see there is ways to do it with regex, but I want to know if I can do it something like the above.
Currently it's failing, because it thinks I'm trying to replace a list with a list.
You can use a dictionary to create pairs which you want replace and iterate other dictonary:
replace_pairs = { 'a': '0', 'b': '1', 'c': '2' }
data = 'abcba'
for key, value in replace_pairs.items():
data = data.replace(key, value)
Output:
>> data = '01210'
I would recommend the regex method, because the runtime is much shorter: How to replace multiple substrings of a string?

What is the best way to store the results of str.split() into a dictionary as part of a list comprehension? [duplicate]

This question already has answers here:
How to split a string within a list to create key-value pairs in Python
(5 answers)
Closed 4 years ago.
Given the following sample data:
values=['A 1','B 2','C 3']
I want to create a dictionary where A maps to 1, B to 2, and C to 3. The following works, but there is repetition:
my_dict={value.split()[0]:value.split()[1] for value in values}
The repetition of value.split() looks ugly. Is there a way to more elegantly create the dictionary without repeating value.split()?
Two ways I can think of:
>>> {k:v for k,v in (s.split() for s in values)}
{'A': '1', 'B': '2', 'C': '3'}
>>> dict(s.split() for s in values)
{'A': '1', 'B': '2', 'C': '3'}
I suggesting reading about the dict type: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict; in particular:
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.
as well as the introduction of dict-comprehensions in PEP 274:
The semantics of dict comprehensions can actually be demonstrated in stock Python 2.2, by passing a list comprehension to the built-in dictionary constructor:
>>> dict([(i, chr(65+i)) for i in range(4)])
is semantically equivalent to:
>>> {i : chr(65+i) for i in range(4)}
For a functional solution, you can use dict with map and str.split:
values = ['A 1', 'B 2', 'C 3']
res = dict(map(str.split, values))
{'A': '1', 'B': '2', 'C': '3'}
you can do this way pythonic:
>>> values =['A 1','B 2','C 3']
>>> dict(map(str.split, values))
{'A': '1', 'C': '3', 'B': '2'}
str.split([sep[, maxsplit]])
Return a list of the words in the string, using sep as the delimiter string. If maxsplit is given, at most maxsplit splits are done (thus, the list will have at most maxsplit+1 elements). If maxsplit is not specified or -1, then there is no limit on the number of splits (all possible splits are made).
If sep is given, consecutive delimiters are not grouped together and are deemed to delimit empty strings (for example, '1,,2'.split(',') returns ['1', '', '2']). The sep argument may consist of multiple characters (for example, '1<>2<>3'.split('<>') returns ['1', '2', '3']). Splitting an empty string with a specified separator returns [''].
map(function, iterable, ...)
Apply function to every item of iterable and return a list of the results. If additional iterable arguments are passed, function must take that many arguments and is applied to the items from all iterables in parallel. If one iterable is shorter than another it is assumed to be extended with None items. If function is None, the identity function is assumed; if there are multiple arguments, map() returns a list consisting of tuples containing the corresponding items from all iterables (a kind of transpose operation). The iterable arguments may be a sequence or any iterable object; the result is always a list.
you can see that dictionary is not in ordered as your list. Using collections.orderedDict we can retain the order of the input given.
>>> import collections
>>> values =['A 1','B 2','C 3']
>>> my_ordered_dict = collections.OrderedDict(map(str.split, values))
>>> my_ordered_dict
OrderedDict([('A', '1'), ('B', '2'), ('C', '3')])

Converting colon separated list into a dict?

I wrote something like this to convert comma separated list to a dict.
def list_to_dict( rlist ) :
rdict = {}
i = len (rlist)
while i:
i = i - 1
try :
rdict[rlist[i].split(":")[0].strip()] = rlist[i].split(":")[1].strip()
except :
print rlist[i] + ' Not a key value pair'
continue
return rdict
Isn't there a way to
for i, row = enumerate rlist
rdict = tuple ( row )
or something?
You can do:
>>> li=['a:1', 'b:2', 'c:3']
>>> dict(e.split(':') for e in li)
{'a': '1', 'c': '3', 'b': '2'}
If the list of strings require stripping, you can do:
>>> li=["a:1\n", "b:2\n", "c:3\n"]
>>> dict(t.split(":") for t in map(str.strip, li))
{'a': '1', 'b': '2', 'c': '3'}
Or, also:
>>> dict(t.split(":") for t in (s.strip() for s in li))
{'a': '1', 'b': '2', 'c': '3'}
If I understand your requirements correctly, then you can use the following one-liner.
def list_to_dict(rlist):
return dict(map(lambda s : s.split(':'), rlist))
Example:
>>> list_to_dict(['alpha:1', 'beta:2', 'gamma:3'])
{'alpha': '1', 'beta': '2', 'gamma': '3'}
You might want to strip() the keys and values after splitting in order to trim white-space.
return dict(map(lambda s : map(str.strip, s.split(':')), rlist))
You mention both colons and commas so perhaps you have a string with key/values pairs separated by commas, and with the key and value in turn separated by colons, so:
def list_to_dict(rlist):
return {k.strip():v.strip() for k,v in (pair.split(':') for pair in rlist.split(','))}
>>> list_to_dict('a:1,b:10,c:20')
{'a': '1', 'c': '20', 'b': '10'}
>>> list_to_dict('a:1, b:10, c:20')
{'a': '1', 'c': '20', 'b': '10'}
>>> list_to_dict('a : 1 , b: 10, c:20')
{'a': '1', 'c': '20', 'b': '10'}
This uses a dictionary comprehension iterating over a generator expression to create a dictionary containing the key/value pairs extracted from the string. strip() is called on the keys and values so that whitespace will be handled.

Adding Items to Python Dictionary

I may have understood this wrong but looking at the examples found in "Learning Python" by O'Reilly I tried to do the following:
>>> d={}
>>> d['h']='GG'
>>> d['f']='JJ'
>>> d['h']='PP'
>>> print d
{'h': 'PP', 'f': 'JJ'}
Now instead of the 'key' 'h' having two entries 'GG' and 'PP' it only has the last entry, the last one replacing the first one.
I want BOTH in the same key.
>>> d['h']+='RR'
>>> print d
{'h': 'PPRR', 'f': 'JJ'}
Again this doesn't work, what I wanted was not a concatenated string but comma-separated entires.
I am confused why this does not work.
Your use-case is handled nicely by the collections.defaultdict() type instead:
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> d['h'].append('GG')
>>> d['f'].append('JJ')
>>> d['h'].append('PP')
>>> d
defaultdict(<type 'list'>, {'h': ['GG', 'PP'], 'f': ['JJ']})
A regular dictionary maps one key to one value, if you want that value to be a list, then you should make it a list, and append to the list instead.
You don't have to use a defaultdict() object, you can always make your values explicit lists:
>>> d = {}
>>> d['h'] = ['GG']
>>> d['f'] = ['JJ']
>>> d['h'].append('PP')
>>> print d
{'h': ['GG', 'PP'], 'f': ['JJ']}
but now you need to create the lists explicitly. The latter problem can then be circumvented again by using dict.setdefault():
>>> d = {}
>>> d.setdefault('h', []).append('GG')
>>> d.setdefault('f', []).append('JJ')
>>> d.setdefault('h', []).append('PP')
which is just a more verbose way of using what defaultdict() objects can provide directly.
It sounds like you want your dictionary to have 'h' map to a list of strings, which you can do as follows:
>>> d={}
>>> d['f']='JJ'
>>> d['h']=['PP']
>>> d['h'].append( 'RR' )
>>> d
{'h': ['PP', 'RR'], 'f': 'JJ'}
If you want all the keys of your dictionary to map to a list (instead of just 'h'), you can use collection.defaultdict as demonstrated in #MartijnPieters's answer.

Categories