How to find if username exist inside a file in Python - python

I have created an archive(usersfile.txt) that contains the users information,
i want when i insert the username, if the username exist in the file return that the user exists and to refer me to the profile of the user(the profile is ok).Τhe problem is that i cannot find the user in the file.
The file is like:
{'user': 'mark', 'age': '20', 'city': ' london '},
{'user': 'jason', 'age': '28', 'city': ' london '},
{'user': 'john', 'age': '25', 'city': ' london '},
{'user': 'pit', 'age': '24', 'city': ' london '}
When i insert the first username ('mark) it works but when i insert the other usernames doesn't work.any suggestion?
is it better to do it with regex?(but i don't know how)
username = input('Enter Username:')
with open(usersfile.txt, 'r', encoding = 'utf-8') as f :
userfiles=[]
for userf in f:
userf = userf.split()
userfiles.append(userf)
for names in userfiles:
if username in names:
print('User {} exist :'.format(username))
UserProfile()
return True
else:
print('User {} doesn't exist :'.format(username))
return False

>>> user_props = {'user': 'mark', 'age': '20', 'city': ' london '},
{'user': 'jason', 'age': '28', 'city': ' london '},
{'user': 'john', 'age': '25', 'city': ' london '},
{'user': 'pit', 'age': '24', 'city': ' london '}
>>> # to find the person
>>> for person in user_props:
user_name = person.get('user')
if user_name and user_name == 'mark':
print(person)
{'user': 'mark', 'age': '20', 'city': ' london '}
>>> # just check if mark is a user
>>> any([it for it in user_props if it.get('user') is 'mark'])
True

You're going to want to do a binary search as this will be the fastest for searching a file of say usernames. For more information on a binary search look at this library for Python and this article. Another more purely vanilla Python way would be to load in the JSON and then loop through each user.
(Bad) Way
We load in the JSON with either an eval or the JSON library. Since you don't want to use other modules we'll use an eval. This is bad for many reasons mainly security and bugs that can break the program.
with open("users.txt") as f_in:
eval("data="+f_in.read())
Now that we have the "JSON" loaded in a variable, data, we can loop through the list of dictionaries and test for your user.
for u in data:
if u["user"] == user:
print("Found user: "+str (u))
break
Binary Search Method
One of the first things you'll want to do is sort the file, also making it either CSV or JSON will help rather than just plain text. I think CSV is best in this case so we'll create a users.csv file with the following content.
user,age,city
jason,28,london
john,25,london
mark,20,london
pit,24,london
And then our Python code will load the file and get the first column of user names. The most efficient way to do the binary search would be to keep the usernames sorted from the start. So when appending a name to the file or list of users you must insert it at the correct index such that the list will be sorted.
import csv
import pandas as pd
from bisect import bisect_left
with open("users.csv") as f_in:
df = pd.read_csv(f_in)
f_in.seek(0)
rows = [r for r in csv.reader(f_in)]
pos = bisect_left(df.name, user)
pos = pos if pos != len(df.name) and df.name[pos] == user else -1
if pos < 0:
print("The user was not found.")
else:
properties = "\n".join([x for x in rows[pos+1]])
print(f"User: {user} was found with properties:\n{properties}")

Related

How can I read a CSV into a Python dictionary, where each key's value is a list of dicts?

I have a CSV file (staff) that looks like this:
id, name, title
1, Steve, Customer Service Manager
2, Martin, Warehouse Operator
3, Jonathan, Backend Developer
I want to parse this into the format:
staff = {
'1':[{'name':'Steve'}, {'title':'Customer Service Manager'}],
'2':[{'name':'Martin'}, {'title':'Warehouse Operator'}],
'3':[{'name':'Jonathan'}, {'title':'Backend Developer'}]
}
But as far as I can tell, the csvreader and pandas libraries don't support this type of operation. Is there a clean way to do this, perhaps with comprehension?
I think DictReader may be a good solution:
with open("sample.csv", "r") as f_csv:
reader = csv.DictReader(f_csv)
data = [row for row in reader]
staff = {r["id"]: [{k: v} for k, v in r.items() if "id" not in k] for r in data}
print(staff)
output:
{'1': [{'name': 'Steve'}, {'title': 'Customer Service Manager'}], '2': [{'name': 'Martin'}, {'title': 'Warehouse Operator'}], '3': [{'name': 'Jonathan'}, {'title': 'Backend Developer'}]}
notes
I modified the csv not to have comma and space to separate fields. Also, this allows any number of other fields, rather than hardcoding just the two shown here. This also combines both dict and list comprehensions.
I created a CSV file and copied the exact data you shared, the following code is giving the desired results.
Code:
import csv
with open('some.csv', newline='') as f:
reader = csv.reader(f)
dict_ = {}
for row in reader:
if(row[0].isnumeric()):
dict_[row[0]] = [{"name":row[1]},{"Title":row[2]}]
print(dict_)
Output:
{'1': [{'name': ' Steve'}, {'Title': ' Customer Service Manager'}], '2': [{'name': ' Martin'}, {'Title': ' Warehouse Operator'}], '3': [{'name': ' Jonathan'}, {'Title': ' Backend Developer'}]}
The reader returns a 2D list which is as follows :
[
['id', ' name', ' title'],
['1', ' Steve', ' Customer Service Manager'],
['2', ' Martin', ' Warehouse Operator'],
['3', ' Jonathan', ' Backend Developer']
]
The code operates on this list using a for loop to append the data in a dictionary in the needed format.
Here the code
import csv
with open('staff.csv', 'r') as f:
reader = csv.reader(f)
data = {}
next(reader) # Skip header
for row in reader:
#print(f"Row : {row}")
id,name,title = row
data [id] = [{'name': name} , {'title': title}]
Exemple of output
{'1': [{'name': ' Steve'}, {'title': ' Customer Service Manager'}], '2': [{'name': ' Martin'}, {'title': ' Warehouse Operator'}], '3': [{'name': ' Jonathan'}, {'title': ' Backend Developer'}]}
If you want to remove the the space in name and title you can use the function strip.
pop and DictReader can provide a one line solution:
with open('data.csv') as fd:
rd = csv.DictReader(fd)
data = {k.pop('id'): k for k in rd}

Read attribute names and return attribute information from dictionary

I am trying to write a simply query that will return all the attributes requested. The idea is to read the attributes names and return attribute information. It should start with the string 'select' and then followed by a list of the attributes the user wants to see
So, there is a small database consisting of dictionaries:
dsql_table =
[{'name': 'Jan', 'type': 'man', 'profession': 'Analyst'},
{'name': 'Max', 'type': 'man', 'profession': 'Doctor'}]
And the idea is to only implement the functionality (disregarding error handling):
try:
query = input('dsql> ')
while query != 'exit':
# I need to implement code over here
print ('Thank you!')
How can I do this without using classes? So if one input e.g. 'select name type', then it should return 'michiel man
Jan man'.
First you need to get the attribute names from the query, then it's quite simple.
dsql_table = [
{'name': 'Jan', 'type': 'man', 'profession': 'Analyst'},
{'name': 'Max', 'type': 'man', 'profession': 'Doctor'},
]
query = 'select name type'
# extract selected attributes from query
selected_attributes = query.split()[1:]
result = []
for record in dsql_table:
# iterate over selected attributes, store value if attribute exists
for attribute in selected_attributes:
if attribute in record:
result.append(record[attribute])
# now result is a list ['Jan', 'man', 'Max', 'man']
print(' '.join(result))
Alternatively, result can be populated using a list comprehesion:
result = [
record[attribute]
for record in dsql_table
for attribute in selected_attributes
if attribute in record
]

Parsing data in a JSON file

I am wanting to parse some information from a JSON file. I cant find a find to successfully retrieve the data I want.
In a file I want to output the profile name.
This is the code on how I am reading and parsing.
with open(json_data) as f:
accounts = dict(json.loads(f.read()))
shell_script = accounts['OCredit']['Profile Name']
print(shell_script)
This gives me the output of
OCredit
In a sense this is what I want, but in the application the value thats now "OCredit"(first bracket) would depend on the user.
with open(json_data) as f:
accounts = dict(json.loads(f.read()))
shell_script = accounts['OCredit']
print(shell_script)
This outputs :
{'Profile Name': 'OCredit', 'Name': 'Andrew Long', 'Email':
'asasa#yahoo.com', 'Tel': '2134568790', 'Address': '213 clover ','Zip':
'95305', 'City': 'brooklyn', 'State': 'NY','CreditCard':'213456759090',
'EXP': '12/21', 'CVV': '213'}
The actual JSON file is :
{'OCredit': {'Profile Name': 'OCredit',
'Name': 'Andrew Long',
'Email': 'asasa#yahoo.com',
'Tel': '2134568790',
'Address': '213 clover ',
'Zip': '95305',
'City': 'Brooklyn',
'State': 'NY',
'CreditCard': '213456759090',
'EXP': '12/21',
'CVV': '213'}}
So, to sum it up. I want to get inside JSON file and just print out the value that "Profile Name" has without hardcoding the fist value of the bracket.
Im not sure if I have to change the way im saving the JSON file to achieve this. Any help would be appreciated.
Try this:
for key in accounts:
print(accounts[key]['Profile Name'])
# OCredit
Or:
for value in accounts.values():
print(value['Profile Name'])

Split dictionary field

I've managed to figure out how to run a SQL query to display information. I need to keep the data in the same form as the db tables, so I think I should be using a dictionary. So far, my fields are ID and Name, my print looks like this:
[{'ID': '123', 'Name': 'ROBERTSON*ROBERT'}, {'ID': '456', 'Name': 'MICHAELS*MIKE'}, {'ID': '789', 'Name': 'KRISTENSEN*KRISTEN'}, ...]
First, am I appropriately using dictionary?
Next, I need to split the Name field based on the * delimiter. For example:
Before:
{'ID': '789', 'Name': 'KRISTENSEN*KRISTEN'}
After:
{'ID': '789', 'LastName': 'KRISTENSEN', 'FirstName': 'KRISTEN'}
I've tested out a few things of code I've found but keep hitting roadblocks. I've used this to create my dictionary, I'm wondering if I include a split in this line to reduce a step?
query = [dict(zip(['ID', 'Name'],row)) for row in cursor.fetchall()]
Like so maybe:
query = [dict(zip(['ID', 'FirstName', 'LastName'], row[:1] + row[1].split('*'))) for row in cursor.fetchall()]
db_dict = {'ID': '789', 'Name': 'KRISTENSEN*KRISTEN'}
name = db_dict['Name']
def split_name(name):
for index, char in enumerate(name):
if char == '*':
position = index
last_name = name[:position]
first_name = name[position + 1:]
return {'LastName':last_name, 'FirstName':first_name}
new_db_dict = {db_dict.keys()[0] : db_dict.values()[0]}
new_db_dict.update(split_name(name))
print new_db_dict
First, while your use of dictionaries is valid I recommend using namedtuples for representing fixed structures with named fields
from collections import namedtuple
# structure class factory
Person = namedtuple("Person", ("id", "name"))
people = [ Person('123', 'ROBERTSON*ROBERT'), Person('456','MICHAELS*MIKE'), Person('789', 'KRISTENSEN*KRISTEN')]
# different structure
PersonName = namedtuple("Person", ("id", "first", "last"))
# structure transformation
def person_to_personname(person):
"""Transform Person -> PersonName"""
names = person.name.split('*')
if len(names) < 2: # depends on your defaults
last = names[0]
first = ''
else: # assumes first field is last name
last, first = names[:2] # even if other names present, takes first two
return PersonName(person.id, first, last)
people_names = [person_to_personname(person) for person in people]
If all entries have a name split by an asterix
A solution in two steps. Once you've retrieved your current results :
a = [{'ID': '123', 'Name': 'ROBERTSON*ROBERT'}, {'ID': '456', 'Name': 'MICHAELS*MIKE'}, {'ID': '789', 'Name': 'KRISTENSEN*KRISTEN'}]
result = [{'ID' : entry['ID'], 'LastName' : entry['Name'].split('*')[0], 'FirstName' : entry['Name'].split('*')[1]} for entry in a]
now if you print result :
[{'FirstName': 'ROBERT', 'ID': '123', 'LastName': 'ROBERTSON'},
{'FirstName': 'MIKE', 'ID': '456', 'LastName': 'MICHAELS'},
{'FirstName': 'KRISTEN', 'ID': '789', 'LastName': 'KRISTENSEN'}]
Otherwise (assuming that the field 'Name' is at least populated)
results = []
for entry in a:
name = entry['Name'].split('*')
result = dict(ID = entry['ID'], LastName = name[0])
if len(name) > 1:
result['FirstName'] = name[1]
results.append(result)

find corresponding key,values and return?

I have a dictionary
cities = {1:'Kompong Som', 2: 'Kompong Thom', 3: 'Phnom Penh'}
tags = {1: 'school', 2: 'public', 3: 'private'}
kwargs = {'city': '2', 'tag': '3'}#should be improve
I want to get output like this :
kwargs = {'city': 'Kompong Thom', 'tag': 'private'}
EDIT
passed from URL
keyword = customer_type=&last_contact=&tag=2,3&city=3&sale_volume=&acc_creation=&last_sale=&key_comm=
in this case
tag=2,3&city=3 maybe in other case tag=2&city=1,2,3 or tag=1,2,3&city=1,2,3
def present_filter(self, list_result, keyword):
##todo: the present filter should be friendly with user .
if len(list_result) > 0:
keywords = eval(json.dumps(keyword))
new_keywords = {}
for key,value in keywords.items():
if value != '' :
new_keywords[key] = value
return new_keywords
# Now new_keywords is {'city': '3', 'tag': '2,3'}
# I WANT TO BE LIKE THIS
#new_keywords is {'city': 'Phnom Penh', 'tag': 'public,private'}
else:
return ''
def translate(cities, tags, kwargs):
return {'city': cities[int(kwargs['city'])],
'tag': tags[int(kwargs['tag'])]}
There's no clear way (from your question) to automate the keyname-to-auxiliary dictionary choice, so I've just hardcoded the keys and aux dict to use for each; if that's not what you want, please edit your question to clarify what it is that you want!-)
Edit: so given this new and different spec from the OP:
# Now new_keywords is {'city': '3', 'tag': '2,3'}
# I WANT TO BE LIKE THIS
#new_keywords is {'city': 'Phnom Penh', 'tag': 'public,private'}
the solution becomes:
def commaplay(adict, value):
return ','.join(adict[int(x)] for x in value.split(','))
def translate(cities, tags, kwargs):
return {'city': commaplay(cities, kwargs['city']),
'tag': commaplay(tags, kwargs['tag'])}
Of course, if the OP completely changes their specs again, the solution will change once more in response (wouldn't it be just incredibly great if people said what they meant, and meant what they said, instead of whirling things around all the time?!-).
You could put cities and tags in a helper dictionary to make it more easy to select the correct values using the kwargs keys:
choices = {
'city': cities,
'tag': tags
}
result = {}
for k, v in kwargs:
result[k] = choices[k][int(v)]

Categories

Resources