Python 2 dicts merge - python

I am creating a dict to hold name and phone number, storing to local by pickle.
the issue now I am facing is: it seems like the merge is not working fine.
, any idea? thanks.
import pickle
def add(name,contact):
person= {};
person[name] = contact;
print('new added: ',person);
mycontactfile = 'contactlist.txt';
f = open(mycontactfile,'rb');
storedcontact = pickle.load(f);
f.close();
print('saved list:',storedcontact);
storedcontact.update(person); # add a new contact to the list
f = open(mycontactfile,'wb');
pickle.dump(storedcontact,f);
print('now full list is:' ,storedcontact);

If you have multiple contacts to go with a name, you'll need a dict of list. You would add contacts like this
if name in storedcontact:
storedcontact.append(contact)
else:
storedcontact[name] = contact
Better yet, stop using pickles and switch to sqlite
Aside:
you can also initialise person in one step like this (but you don't really need person anymore)
person = {name: contact}

Related

Python searching for an object by ID prior to insertion into a list

I am reading several CSV files. I do not have prior knowledge if the files contain duplicate customer information.
class customerIdentityCard:
def __init__(self, id=0, firstName="", lastName=""):
self.id = id.upper() # alphanumeric field
self.firstName = firstName.upper()
self.lastName = lastName.upper()
before I blindly do a:
customerList = []
#in my for loop reading data from csv file
customerList.append(customerIdentityCard(field[0],field[1],field[2])
I want to check if the customer already exists in my customerList.
Since I know each customer has a unique ID number, I don't care if the other fields have spelling errors or other name variations. Just want to be sure that I am not putting duplicate IDs in my list.
Using Python 3.9.5 on Windows.
I would use a set() to maintain a unique list of ids that have been added already. set() is a little like a list that only contains unique elements but it is also fast to search. As other have suggested, there are also ways to solve this with a dict though.
Maybe this to get started with:
all_customers = [] ## list from your csv
unique_customers = set()
customerList = []
for customer in all_customers:
if customer[0] in unique_customers:
continue
customerList.append(customerIdentityCard(customer[0],customer[1],customer[2]))
unique_customers.add(customer[0])

Parsing and arranging text in python

I'm having some trouble figuring out the best implementation
I have data in file in this format:
|serial #|machine_name|machine_owner|
If a machine_owner has multiple machines, I'd like the machines displayed in a comma separated list in the field. so that.
|1234|Fred Flinstone|mach1|
|5678|Barney Rubble|mach2|
|1313|Barney Rubble|mach3|
|3838|Barney Rubble|mach4|
|1212|Betty Rubble|mach5|
Looks like this:
|Fred Flinstone|mach1|
|Barney Rubble|mach2,mach3,mach4|
|Betty Rubble|mach5|
Any hints on how to approach this would be appreciated.
You can use dict as temporary container to group by name and then print it in desired format:
import re
s = """|1234|Fred Flinstone|mach1|
|5678|Barney Rubble|mach2|
|1313|Barney Rubble||mach3|
|3838|Barney Rubble||mach4|
|1212|Betty Rubble|mach5|"""
results = {}
for line in s.splitlines():
_, name, mach = re.split(r"\|+", line.strip("|"))
if name in results:
results[name].append(mach)
else:
results[name] = [mach]
for name, mach in results.items():
print(f"|{name}|{','.join(mach)}|")
You need to store all the machines names in a list. And every time you want to append a machine name, you run a function to make sure that the name is not already in the list, so that it will not put it again in the list.
After storing them in an array called data. Iterate over the names. And use this function:
data[i] .append( [ ] )
To add a list after each machine name stored in the i'th place.
Once your done, iterate over the names and find them in in the file, then append the owner.
All of this can be done in 2 steps.

Dictionary entry not working as intended, only last entry getting inserted-Python

Working on this for learning experience. The 3 ideas below I came up with
A) User creates a profile so I have a dictionary for fname and lname.
B)Then I randomly generate userid add that to a list. This list only contains random user id that I will user later eg: userid012,userid89
C) I assign A and B in a new dictionary. Output looks like this:
used_id user3
profile {'lastname': 'jon', 'firstname': 'jme'}
problem: I only see the last values user id and names. If I have more than 2 entries, I do not see the 1st ones. Helpful hint would be really helpful.
Thank You.
import random
print('Enter choice 1-3:'),'\n'
print('', '1-Create new profile','\n',
'2-Update existing profile','\n',
'3-Delete a profile')
#global variables
choice=int(input())
user_directory={}
#Dictionary function that takes fst and lst name and puts in a dict:
def new_profile():
new_profile={}
fn=input('First name:')
new_profile['firstname']=fn
ln = input('Last name:')
new_profile['lastname'] = ln
for k,v in new_profile.items():
new_profile[k]=v
return new_profile
#Generates a random user id which we will assign to a user created above
def user_id():
uid_list=[]
user_id='user'+str(random.randint(0,101))
uid_list.append(user_id)
if(user_id in uid_list):
uid_list.remove(user_id)
user_id = 'user' + str(random.randint(0, 101))
uid_list.append(user_id)
return user_id
#This dictionary will have user id and associate created new_profile
def addToDict():
#user_directory={} unable to use this making it global
user_directory['used_id']=user_id()
user_directory['profile']=new_profile()
for key,value in user_directory.items():
user_directory[key]=value
return user_directory
if(choice==1):
# myuser=addToDict() this appraoch did not work
#addToDict>> adding it here will not get this option in while loop, put inside while
while True:
addToDict()
print('Add another entry?')
choice=input()
#Put the line below to see if number increases
print('Current', len(user_directory)-1)
if(choice!='stop'):
continue
else:
break
for k,v in user_directory.items():
print(k,v)
Bad indentation in the last line of new_profile(). The return is running on the first iteration. Try:
for k,v in new_profile.items():
new_profile[k]=v
return new_profile
Btw, you don't seem to be following most conventions/standards in Python. Take a look at this simple tutorial about PEP, the official style guide. This way you can make better looking code and we can help faster :)
Your code contains a couple of bugs. I can only guess what you want to do. Lets start with the obvious: The function addToDict() should probably add a new user to the dictionary.
What you usually want is to have a dictionary which maps a user_id onto a profile:
def addUserToDict(user_dictionary, user_id, profile):
user_directory[user_id] = profile
And then in the input loop below you call this function with your dictionary, a new user id and a new profile.
A second bug is in user_id(): You always return a list with one new element, with a new random user id. And you always discard the first generated user id and then you add a second one.

Dynamically generated Class instances

I want to store values that I plan to later use for sorting pdfs on my computer using PyPDF2.
I thought that if I created a class and stored identifying info for each type of file (such as a descriptor, a string that is unique to the file and can be found by PyPDF2 later such as an account number, and the path where the file should be moved to) that would work. Something like this:
class File_Sort(object):
def __init__(self, identifier, file_text, file_path):
self.identifier = identifier
self.file_text = file_text
self.file_path = file_path
so an example input from me would be:
filetype0001 = File_Sort("Phone Bill", "123456", "/Users/Me/PhoneBills/")
I would like to be able to have users generate new file types via a series of raw_input questions, but I can't figure how to generate the variable to create a new instance, so that I can get:
filetype000[automatically incrementing number] = File_Sort(UserResponse1, UserResponse3, UserResponse3).
Creating the "filetype000[automatically incrementing number]" text itself seems easy enough with:
file_number += 1
file_name = "filetype" + str(file_number).zfill(4)
but how do you turn the generated file_name string into a variable and populate it?
It sounds like you're wanting to dynamically create variables. That's almost always a foolish thing to do. Instead, you should be using a data structure like a list or dictionary, indexed by the parts of the variable name you wanted to generate dynamically.
So instead of creating a list named filetype000, start with a list named filetypes, and append an inner list, so you can do filetypes[0] to get at it. Or if string names make more sense for your specific application, let filetypes be a dictionary, and access the inner lists with something like filetypes['pdf'].
I'm being a little vague here because I don't really understand all of your pseudocode. It's not at all obvious what the purpose of the [automatically incrementing number] parts of your example are, so I'm more or less ignoring those bits. You probably just want to start with an empty list and append values to it, rather than somehow initializing it to a specific size and magically indexing it.
so fyi this is what I ended up using:
file_descriptor = []
file_string = []
file_location = []
filetype_new = len(file_descriptor)
input_descriptor = raw_input("What is the description of the new file type? ")
file_descriptor.append(input_descriptor)
input_filestring = raw_input("What is unique string to search for in this file type? ")
file_string.append(input_filestring)
input_filelocation = raw_input("where should we put this file type? ")
file_location.append(input_filelocation)
print("file%s: %s, \t%s, \t%s" % (str(filetype_new+1).zfill(4), file_descriptor[filetype_new], file_string[filetype_new], file_location[filetype_new]))
review = raw_input("\nWould you like to review the current files? y/n ").lower()
while review not in "yn":
review = raw_input("Sorry, I don't understand. Would you like to review your file types? y/n ").lower()
print("There are currently sort instructions for %s filetypes: " % (len(file_descriptor)))
file_increment = 0
while file_increment in range(0, len(file_descriptor)):
print("file%s: %s, \t%s, \t%s" % (
str(file_increment + 1).zfill(4), file_descriptor[file_increment], file_string[file_increment],
file_location[file_increment]))
file_increment += 1
thanks for your advice.

Make a list with a name that is only known after the program runs

I want to make a list and call it a name which I only know after I run the program:
For example:
#making shelfs
group_number = 1
group_name = 'group' + str(group_number)
print group_name
group_name will be: group1
Now I want to make an empty list called group1. How to do such a thing?
Usually you just put this into a dictionary:
d = {group_name:[]}
Now you have access to your list via the dictionary. e.g.:
d['group1'].append('Hello World!')
The alternative is to modify the result of the globals() function (which is a dictionary). This is definitely bad practice and should be avoided, but I include it here as it's always nice to know more about the tool you're working with:
globals()[group_name] = []
group1.append("Hello World!")
You are wanting to create a pseudo-namespace of variables starting with "group". Why not use a dict instead?
#making shelfs
groups = {}
group_number = 1
name = str(group_number)
groups[name] = [] # or whatever
print groups[name]
This is subtly different to #mgilson's answer because I am trying to encourage you to create new namespaces for each collection of related objects.
you do this:
locals()['my_variable_name'] = _whatever_you_wish_
or
globals()['my_variable_name'] = _whatever_you_wish_
or
vars()['my_variable_name'] = _whatever_you_wish_
Google to find out the differences yourself :P

Categories

Resources