Converting a string to a dictionary - python

I am trying to convert string into Dictionary in Python. I have tried the following but getting the error
'dict' object is not callable. Please help me solve this problem.
l=[]
str='Vijay=23,Ganesh=20,Lakshmi=19,Nikhil=22'
for x in str.split(','):
y=x.split('=')
l.append(y)
d=dict(l)
for k in d:
print('{:1s}---{:1s}'.format(k,d[k]))

s = 'Vijay=23,Ganesh=20,Lakshmi=19,Nikhil=22'
dct = {n: a for n, a in (p.split("=") for p in s.split(","))} #Credits to JL0PD
print(dct)
#{'Vijay': '23', 'Ganesh': '20', 'Lakshmi': '19', 'Nikhil': '22'}

l=[]
str='Vijay=23,Ganesh=20,Lakshmi=19,Nikhil=22'
for x in str.split(','):
y=x.split('=')
l.append(y)
result = {}
for item in l:
result[item[0]] = item[1]
print(result)

You override the reserved word str.
In python the word str is the name of the class string.
When you wrote str = 'Vijay=23,Ganesh=20,Lakshmi=19,Nikhil=22',
you changed the class str to be 'Vijay=23,Ganesh=20,Lakshmi=19,Nikhil=22'
run this code:
l = []
string = 'Vijay=23,Ganesh=20,Lakshmi=19,Nikhil=22'
for x in string.split(','):
y = x.split('=')
l.append(y)
d = dict(l)
for k in d:
print('{:1s}---{:1s}'.format(k,d[k]))
Same code but follows PEP8 rules
pars_list = []
row_data = 'Vijay=23,Ganesh=20,Lakshmi=19,Nikhil=22'
for i in row_data.split(','):
pars_list.append(i.split('='))
data = dict(l)
for k in data.keys():
print('{:1s}---{:1s}'.format(k, data[k]))

Give this a try.
Step1
Iterate through ['Vijay=23', 'Ganesh=20', 'Lakshmi=19', 'Nikhil=22']
Step2
Split every person by =. ['Nikhil', '22']
Step3
Add the first element to the dict as a key and the age to the dict as a value
peopleDict = {people.split('=')[0]:int(people.split('=')[1]) for people in string.split(',')}
output
{'Vijay': 23, 'Ganesh': 20, 'Lakshmi': 19, 'Nikhil': 22}
#Note1: Make sure you do not name your variable str or int, input etc. These are all methods created by python, don't overide them.
#Note2: my output turns all the ages into integers just in case you need to manipulate them later on in your code.

Related

List comprehension if/else and for iteration order

I have a CSV file that contains book chapters either as single chapters or chapter ranges delimited by commas, e.g. 1,2,4-6,12.
Given this input '1,2,4-6,12', I want a list ['1','2','4','5','6','12'] as output
Something along the lines of:
chps=[str(x) for x in chp_range(entry)) if '-' in entry else entry for entry in chapters.split(',') ]
which doesn't work.
Function chp_range('4-6') returns a range(4,6) object.
I've tried a lot of variations, but still haven't been able to get the order of conditionals and iteration right. How can I get this code to work?
If it has to be a one-liner, this should work:
>>> [str(x) for c in chapters.split(",") for x in range(int(c.split("-")[0]), int(c.split("-")[-1])+1)]
['1', '2', '4', '5', '6', '12']
You can't conditionally nest your comprehensions, so your chp_range function is of little value when used in a comprehension.
Don't try to use list comprehension for the sake of, only if it's actually easier / more readable:
lst = []
for x in s.split(','):
if '-' in x:
start, end = x.split('-')
lst.extend([str(i) for i in range(int(start), int(end)+1)])
else:
lst.append(x)
What you were trying to do:
chps = [str(x)
for entry in chapters.split(',')
for x in (chp_range(entry) if '-' in entry else [entry])]
Try it online!
from itertools import chain
def chp_range(entry):
x, y = map(int, entry.split('-'))
return map(str, range(x, y+1))
chps = [
chp_range(entry) if '-' in entry else entry for entry in chapters.split(',')]
list(chain(*chps))
YOu can use extend for range as follows:
string = '1,2,4-6,12'
string = string.split(',')
chapters = []
for i in string:
if '-' in i:
a,b = i.split('-')
chapters.extend(range(int(a),int(b)+1))
else:
chapters.append(int(i))
print(chapters)
Not a one-liner but if you are interested in a recursive solution. Please check it up.
a = '1,2,4-6,12'
inp = [num if '-' not in num else [str(i) for i in range(int(num[0]),int(num[-1])+1)] for num in a.split(',') ]
ans = []
def flatten(inp,ans):
while inp:
tmp = inp.pop()
if type(tmp) == str:
ans.append(tmp)
else:
flatten(tmp,ans)
return
flatten(inp,ans)
ans[::-1]

Remove file name duplicates in a list

I have a list l:
l = ['Abc.xlsx', 'Wqe.csv', 'Abc.csv', 'Xyz.xlsx']
In this list, I need to remove duplicates without considering the extension. The expected output is below.
l = ['Wqe.csv', 'Abc.csv', 'Xyz.xlsx']
I tried:
l = list(set(x.split('.')[0] for x in l))
But getting only unique filenames without extension
How could I achieve it?
You can use a dictionary comprehension that uses the name part as key and the full file name as the value, exploiting the fact that dict keys must be unique:
>>> list({x.split(".")[0]: x for x in l}.values())
['Abc.csv', 'Wqe.csv', 'Xyz.xlsx']
If the file names can be in more sophisticated formats (such as with directory names, or in the foo.bar.xls format) you should use os.path.splitext:
>>> import os
>>> list({os.path.splitext(x)[0]: x for x in l}.values())
['Abc.csv', 'Wqe.csv', 'Xyz.xlsx']
If the order of the end result doesn't matter, we could split each item on the period. We'll regard the first item in the list as the key and then keep the item if the key is unique.
oldList = l
setKeys = set()
l = []
for item in oldList:
itemKey = item.split(".")[0]
if itemKey in setKeys:
pass
else:
setKeys.add(itemKey)
l.append(item)
Try this
l = ['Abc.xlsx', 'Wqe.csv', 'Abc.csv', 'Xyz.xlsx']
for x in l:
name = x.split('.')[0]
find = 0
for index,d in enumerate(l, start=0):
txt = d.split('.')[0]
if name == txt:
find += 1
if find > 1:
l.pop(index)
print(l)
#Selcuk Definitely the best solution, unfortunately I don't have enough reputation to vote you answer.
But I would rather use el[:el.rfind('.')] as my dictionary key than os.path.splitext(x)[0] in order to handle the case where we have sophisticated formats in the name. that will give something like this:
list({x[:x.rfind('.')]: x for x in l}.values())

How we can read first element of key from List?

I am new to python. How can I get the first value from list? When I am printing x[0] I am getting EmpId:244.
txt = "EmpId:244|Name:'Adi'|contact_no:1234567890|product_code:538365085|date:2020-04-06|fileName:Report_BGDE_16-Apr-2020|code:ABC|resubmitted:Y|file_format:CSV"
x = txt.split("|")
print(x[0])
I need to return only EmpId. Any solution will help me. Thanks
You need to split once more on : char.
txt = "EmpId:244|Name:'Adi'|contact_no:1234567890|product_code:538365085|date:2020-04-06|fileName:Report_BGDE_16-Apr-2020|code:ABC|resubmitted:Y|file_format:CSV"
object = txt.split("|")[0]
key_value = object.split(':')
key = key_value[0] # EmpId
value = key_value[1] #244
You could use
txt = "EmpId:244|Name:'Adi'|contact_no:1234567890|product_code:538365085|date:2020-04-06|fileName:Report_BGDE_16-Apr-2020|code:ABC|resubmitted:Y|file_format:CSV"
values = (item.split(":") for item in txt.split("|"))
key, value = next(values)
print(value)
You can convert to dict:
my_dict = {k : v for k, v in [item.split(':') for item in txt.split('|')]}
print(my_dict['EmpId'])
'244'
This could also neatly help in case you want more fields other than EmpId later:
dict(item.split(":") for item in txt.split("|"))
On extending Mr. #Jan answer, it is much more easy to store the data into a dictionary than a list or tuple or generator
d = {item.split(":")[0]:item.split(":")[1] for item in txt.split("|")}
Then, any required field can be retrieved using the key as in
d['EmpId'] will give 244
d['product_code'] gives 538365085

Python : convert text file to dict

I would like to convert but I have gotten an error
A 123 132 21
B 34 293 91
d = {}
with open("ab.txt") as f:
for line in f:
(key, val) = line.split()
d[(key)] = val
print(d)
You probably got a "ValueError: too many values to unpack (expected 2)" error.
I am assuming you are trying to create a dictionary where the results will be:
d = {'A': [123, 132, 21], 'B': [34, 293, 91]}
If that is the case, you need:
d = {}
with open("ab.txt") as f:
for line in f:
(key, *val) = line.split() # this will allow val to become a list of the remaining values
d[key] = list(map(lambda x: int(x), val))
print(d)
You were just missing the * before val to cause iterable unpacking: Its operand must be an iterable. The iterable is expanded into a sequence of items, which are included in the new tuple, list, or set, at the site of the unpacking.
Update
From the Python manual concerning the map(function, iterable, ...) function:
Return an iterator that applies function to every item of iterable, yielding 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. With multiple iterables, the iterator stops when the shortest iterable is exhausted. For cases where the function inputs are already arranged into argument tuples, see itertools.starmap().
In this case we use a lambda function as the first argument to map. It takes one argument and converts it to an int.
Then we apply the list() constructor to the iterator returned by the map function to create a list of int items.
Crank up an IDE (you can just type python with no arguments):
>>> val = ['123', '132', '21']
>>> m = map(lambda x: int(x), val)
>>> m
<map object at 0x00000279A94F1358>
>>> list(m)
[123, 132, 21]
Or:
>>> val = ['123', '132', '21']
>>> m = map(lambda x: int(x), val)
>>> for x in m: print(x)
...
123
132
21
And:
>>> l = lambda x, y: x + y
>>> l(7,9)
16
>>>
You can also accomplish the conversion with a list comprehension:
Most people find the list comprehension method easier to read/understand compared with using map, but I wanted to show you both ways:
d = {}
with open("ab.txt") as f:
for line in f:
(key, *val) = line.split() # this will allow val to become a list of the remaining values
d[key] = [int(x) for x in val]
print(d)
Depending on what you want to achieve, either:
replace line.split() with line.split(maxsplit=1) - this way
values of your dict will be strings like "123 132 21"
replace (key, val) = line.split() with (key, *val) = line.split() - this way values of your dict will be lists like [123, 132, 21]
The built-in function str.split() splits a string wherever it finds whitespace when no separator is specified. So, using your first line as an example, the following happens:
>>> 'A 123 132 21'.split()
['A', '123', '132', '21']
Thus, you get too many values to unpack in your definition of the tuple. To fix it, you could use the star * operator (I don't know the proper name for that operator) in front of your variable definition
d = {}
with open("ab.txt") as f:
for line in f:
(key, *val) = line.split()
d[(key)] = val
print(d)
# Prints {'A': ['123', '132', '21'], 'B': ['34', '293', '91']}
This is explained in the Python tutorial.
Another option is to use the named maxsplit parameter of the split() function:
d = {}
with open("ab.txt") as f:
for line in f:
(key, val) = line.split(maxsplit=1)
d[(key)] = val.strip()
print(d)
Note that I had to append strip() when setting the entry to the dictionary to get rid of a trailing newline \n.
Yon can do it this way :
fichier = open("ab.txt", 'r')
d = {}
for line in fichier.readlines():
d[line[0]] = line[2:].rstrip().rsplit(' ')
print(d)
Output :
{'A': ['123', '132', '21'], 'B': ['34', '293', '91']}
Ask me if you don't understand something :).

Most Pyhthonic way to convert element of list get with re

I am using regex to extract some numbers out of a string (lp). I know that the list that I will get out of it will contain only 2 elements. I also know they will both be integers.
Therefore I would like to write this with just one line of code.
home,away = re.findall(r'\d+',lp)
home,away = int(home),int(away)
Thanks for your help
You can use the following :
home, away = map(int, re.findall(r'\d+', lp))
Another idea is to use list comprehension :
home, away = [int(e) for e in re.findall(r'\d+', lp)]
Little trick about managing types when you have a static result length :
expected_types = [int, int, str]
elements = ['1', '2', 'toto']
result = [_type(e) for _type, e in zip(exected_types, elements]
# Returns : [1, 2, 'toto']
Another solution:
home, away = [ int(x) for x in re.findall(r'\d+', lp) ]
Edit: FunkySayu you are faster ...

Categories

Resources