How to copy part of contents in one array to another? - python

I've got a list name users, and I want a second list named account_no to take only the first part of the contents of users.
users = [
'GB1520*Adam Johnson*07293105657',
'ZA5584*Dean Davids*07945671883'
]
account_no = []
def find_accountno():
for index in range(len(users)):
# I want to take the first 6 characters of users[index]
acc = users[index: 6]
account_no.append(acc)
print(users)
find_accountno()
print(account_no)
And this is the desired output:
['GB1520', 'ZA5584']
But, instead, I'm getting this:
[['GB1520*Adam Johnson*07293105657', 'ZA5584*Dean Davids*07945671883'], ['ZA5584*Dean Davids*07945671883']]

You should read a bit more about slicing; you'll see that it doesn't work the way you think it does.
You wrote:
acc = users[index: 6]
This is saying "take every element in users from index index to index 6 (including index, not including 6), form a new list from them, and put them in acc".
For example:
l = [0,1,2]
b = l[0:2]
Would have the list [0,1] inside b.
If what you want is to grab the first six characters of users[index], then you simply want users[index][0:6] (so users[index] is the string you wish to slice; then [0:6] employs slicing as described above to only grab the first 6 elements: 0 to 5). You can also drop the 0 (so [:6]).
Some extras:
Another two solutions, just to show you some fun alternatives (these use what's known as list comprehension):
def find_accountno_alt1():
numbers = [user[:6] for user in users]
account_no.extend(numbers)
def find_accountno_alt2():
numbers = [user.split('*')[0] for user in users]
account_no.extend(numbers)
Another point: I'd personally recommend simply passing the list (account_no) as a parameter to make the method neater and more self-contained.

In your code, you need to use acc=users[index][:6].
users = ['GB1520*Adam Johnson*07293105657', 'ZA5584*Dean Davids*07945671883']
account_no = []
def find_accountno():
for index in range(len(users)):
acc = users[index][:6] #I want to take the first 6 characters of users[index]
account_no.append(acc)
#print(users)
find_accountno()
print(account_no)
As for the multiple output, you are getting that because you are also printing the users list.

I suggest you to split the strings by "*" char and take only the first part (your account id)
account_no = [user.split("*")[0] for user in users]
EDIT:
full code for your task
users = ['GB1520*Adam Johnson*07293105657', 'ZA5584*Dean Davids*07945671883']
account_no = [user.split("*")[0] for user in users]
print(users)
print(account_no)

Here is an alternative and more Pythonic way to write your code and get the results you want:
def find_account_numbers(users):
return [user[:6] for user in users]
users = [
'GB1520*Adam Johnson*07293105657',
'ZA5584*Dean Davids*07945671883'
]
account_numbers = find_account_numbers(users)
print(account_numbers)
The code snippet above will result in the following output:
['GB1520', 'ZA5584']

Related

Edit list element in multilist - Python

I am using python 3.x, I have the following problem, using the keyboard the user enters certain data and fills N lists to create a contact list, then in a list I collect all the data of the lists, I need to modify the data of each list, (I already have it, I modify the data of a list with a specific value using a for) Example, Names list, I modify Andrew's name, but in the Contacts list, there is all Andrew's information (phone, mail, etc), but I just need to modify in the Contacts list, the value of Andrew
I have all this list:
names = []
surnames = []
phones = []
emails = []
addresses = []
ages = []
salaries = []
genres = []
contacts = []
# and use the append to add the data into the contacts list
contacts.append ([names, surnames, phone numbers, emails, addresses, ages, salaries, genders])
Then I update the info of one contact
search = input(Fore.LIGHTBLUE_EX + "Type the name of the contact you want update: ")
for i in range(len(names)):
if (names[i] == search):
try:
names[i] = input(Fore.MAGENTA + "Type the New name: ")
names[i] = nombres[i].replace(" ", "")
if names[i].isalpha() == True:
print(Fore.GREEN + "Already saved, congrats.")
pause= input(Fore.LIGHTGREEN_EX + "Press enter to exit")
But I dont know how to update the name in the List of contacts.
When you call contacts.append(), you add a list of lists to a list, so your contacts list will look something like this:
contacts = [[[names[0], names[1], ...], [...], [...]]]
It's unnecessary to have a list of one item nested in another list, so I would just call contacts.append() and pass each list (names, surnames, etc.) to the method, which allows for easier indexing.
Since the list names would be the first item in the list contacts (contacts[0]), you could do one of two things (there may be more, but these are off the top of my head):
Reassign the specific index to a new value, using nested-list indexing (contacts[0][0] = "updated name" would update the first item of the names list to "update name")
Reassign the entire nested list to a new list (contacts[0] = new_name_list would reassign contacts[0], formerly the names list, to new_name_list)
On a side note: In this case, I would recommend dictionaries over lists, as it will be easier to keep track of what is being reassigned/modified.
contacts = {
"names": names,
"surnames": surnames,
...
}
Doing this will make it more clear which list your are referring to; contacts[0] doesn't give much information, but contacts["names"] informs readers that you are referring to the names list. This is solely for cleaner code; there isn't much difference in functionality.

How can I add two or more elements to a list from a single input in Python?

What my script is doing now is adding elements to a list. For example, if the user types "JO", I will add "John" to the list. What I want to do now is that, if the user types "2 JO", I add two elements to the list: "John" and "John".
This is how the database looks like now:
Sample database copy.png
This is the code now:
import pandas
data = pandas.read_excel("Sample database copy.xlsx")
name = dict(zip(data["Abbreviation"],data["Name"]))
list1 = []
incoming_msg = input(Please type what you want to add: )
list1.append(name[incoming_msg])
I need to do it all from the same input, I cannot ask separately for quantity and abbreviation. I wanted to know if there is any library that can do this somehow easily because I am a beginner coder. If there is no library but you have any idea how I could solve it, it would be awesome as well.
Thank you so much in advance!
you can use string.split() to split the string by space into a list then use the first element to multiply a list that contains the value from the dictionary and increment it to the result list. see the code
name = dict(zip(data["Abbreviation"],data["Name"]))
list1 = []
incoming_msg = input('Please type what you want to add: ')
incoming_msg = incoming_msg.split() # split the string by space
if len(incoming_msg) == 2: # if there are two elements in the list (number and name)
list1 += [name[incoming_msg[1]]] * int(incoming_msg[0])
else:
list1.append(name[incoming_msg[0]])

Generate a random number avoiding duplicates from a given list

I am working on a project and I need to write a function to generate ID's for every client in our the company. There's an existing list of clients already and some of them have a numerical 5 to 6 digits ID ranging from 40,000 to 200,000. There are other existing clients that do not have an ID and I would like to keep consistency with the already existing ID numbers (e.g. 43606 or 125490).
So in order to keep a similar format I created an Exclusion_List that contains all of the existing ID numbers. Then I was going to write a function using np.random.uniform(low=40000, high=200000) so that generates a number within that range that would look similar to the other ID numbers.
The problem that I have is that I don't know how to set a loop to check if the randomly generated ID is already in the exclusion list and if so; to generate a new one then.
This is what I have so far:
exclusions = [43606,125490,...]
def ID_Generator(new_clients): # This is a list of new client
new_client_IDs = []
for client in new_clients:
ID = int(np.random.uniform(low=40000, high=200000))
while ID not in exclusions:
new_client_IDs.append(ID)
I am not sure how to handle the scenario when the randomly generated number is in the exclusion list. I would love the function to output a dataframe containing the client names in one column and the ID number in a second column.
Appreciate any help on this!
Similar answer to Niranjan, but no list comprehension needed,
import numpy as np
import pandas as pd
exlcusion_list = [43606,125490]
free_ids = np.arange(40000, 200000)
free_ids = free_ids[~np.isin(free_ids, exlcusion_list)]
def get_ids(client_names):
new_client_ids = np.random.choice(free_ids, len(client_names), replace=False)
return pd.DataFrame(data=new_client_ids, index=client_names, columns=["id"])
print(get_ids(["Bob", "Fred", "Max"]))
which gives
id
Bob 125205
Fred 185058
Max 86158
Simple approach I can think as of now is.
Generate a list from 40000-200000.
Remove all the exclusions from the above list.
Randomly pick any id from the remaining list (In case order matters, use ids sequentially).
import random
exclusions = [43606,125490]
all = range(40000,200000)
remaining = [x for x in all if x not in exclusions]
random.choice(remaining)
exclusions = [43606,125490,...]
def ID_Generator(new_clients): # This is a list of new client
new_client_IDs = []
while len(new_client_IDs) < len(new_clients):
ID = randint(40000, 200000)
if ID not in exclusions:
new_client_IDs.append(ID)
if list(dict.fromkeys(new_client_IDs)):
new_client_IDs = list(dict.fromkeys(new_client_IDs))

Usage of a random function and lists

Here is my code
N=str(input("Enter the catagory: "))
Countries=["canada","albania","cuba"]
if N=="Countries":
y=random.choice(Countries)
if I do something like this the code takes the elements in the countries but when I try to create a function by using it I fail. For example I have many catogories so I dont want to write if function like 10 times for every catagory.Hence I tried to write it like this
N=str(input("Enter the catagory: "))
Countries=["canada","albania","cuba"]
def cata(N):
y=random.choice(N)
z=len(str(y))
return (z,y)
but at this time when I type countries I only get the letters of the countries so the code refers to the word "countries" but the list name.And I need the elements of the countries list. I am not sure how to fix it
thanks.
Well after the function ends I need both y and z values.
If you have a number of categories, and you need a single function to return a random value from one of those list, depending on the name of the list that you send, I think your best way of doing this is through a dictionary with lists as value. Something like
dic = {
'countries' : ["A","B","C"]
'cities' : ["X","Y","Z"]
}
Now your function can take the name of the list as a parameter, and use it to look up in the dictionary to get the appropriate list, and return a random value from that
N = str(input("Enter the catagory: "))
def cata(n):
y = random.choice(dic[n])
cata(N)
You are confusing a str (a piece of data) with variables and a piece of program code.
If user enters 'Countries' to the input, the string N gets turned into a list ['C', 'o', 'u', ...] inside random.choice(N).
To "fix" your program, you can do it this way:
Countries = ["canada","albania","cuba"]
N = str(input("Enter the catagory: "))
y = random.choice(eval(N))
...
HOWEVER, it is strongly discouraged to apply eval() to a string that user input. Most users can be expected to make mistakes at least some of the time, and a malicious user can abuse it to break your program or even your system.

Combining two lists and sorting through reference to dictionary Python

I have (what seems to me is) a pretty convoluted problem. I'm going to try to be as succinct as possible - though in order to understand the issue fully, you might have to click on my profile and look at the (only other) two questions I've posted on StackOverflow. In short: I have two lists -- one is comprised of email strings that contain a facility name, and a date of incident. The other is comprised of the facility ids for each email (I use one of the following regex functions to get this list). I've used Regex to be able to search each string for these pieces of information. The 3 Regex functions are:
def find_facility_name(incident):
pattern = re.compile(r'Subject:.*?for\s(.+?)\n')
findPat1 = re.search(pattern, incident)
facility_name = findPat1.group(1)
return facility_name
def find_date_of_incident(incident):
pattern = re.compile(r'Date of Incident:\s(.+?)\n')
findPat2 = re.search(pattern, incident)
incident_date = findPat2.group(1)
return incident_date
def find_facility_id(incident):
pattern = re.compile('(\d{3})\n')
findPat3 = re.search(pattern, incident)
f_id = findPat3.group(1)
return f_id
I also have a dictionary that is formatted like this:
d = {'001' : 'Facility #1', '002' : 'Another Facility'...etc.}
I'm trying to COMBINE the two lists and sort by the Key values in the dictionary, followed by the Date of Incident. Since the key values are attached to the facility name, this should automatically caused emails from the same facilities to be grouped together. In order to do that, I've tried to use these two functions:
def get_facility_ids(incident_list):
'''(lst) -> lst
Return a new list from incident_list that inserts the facility IDs from the
get_facilities dictionary into each incident.
'''
f_id = []
for incident in incident_list:
find_facility_name(incident)
for k in d:
if find_facility_name(incident) == d[k]:
f_id.append(k)
return f_id
id_list = get_facility_ids(incident_list)
def combine_lists(L1, L2):
combo_list = []
for i in range(len(L1)):
combo_list.append(L1[i] + L2[i])
return combo_list
combination = combine_lists(id_list, incident_list)
def get_sort_key(incident):
'''(str) -> tup
Return a tuple from incident containing the facility id as the first
value and the date of the incident as the second value.
'''
return (find_facility_id(incident), find_date_of_incident(incident))
final_list = sorted(combination, key=get_sort_key)
Here is an example of what my input might be and the desired output:
d = {'001' : 'Facility #1', '002' : 'Another Facility'...etc.}
input: first_list = ['email_1', 'email_2', etc.]
first output: next_list = ['facility_id_for_1+email_1', 'facility_id_for_2 + email_2', etc.]
DESIRED OUTPUT: FINAL_LIST = sorted(next_list, key=facility_id, date of incident)
The only problem is, the key values are not matching properly with what's found in each individual email string. Some DO, others are completely random. I have no idea why this is happening, but I have a feeling it has something to do with the way I'm combining the two lists. Can anyone help this lowly n00b? Thanks!!!
First off, I would suggest reversing your ID-to-name dictionary. Looking up a value by key is very fast but finding a key by value is very slow.
rd = { name: id_num for id_num, name in d.items() }
Then your first function can be replaced by a list comprehension:
id_list = [rd[find_facility_name(incident)] for incident in incident_list]
This might also expose why you're getting messed up values in your results. If an incident has a facility name that's not in your dictionary, this code will raise a KeyError (whereas your old function would just skip it).
Your combine function is very similar to Python's built in zip function. I'd replace it with:
combination = [id+incident for id, incident in zip(id_list, incident_list)]
However, since you're building the first list from the second one, it might make sense to build the combined version directly, rather than making separate lists and then combining them in a separate step. Here's an update to the list comprehension above that goes right to the combination result:
combination = [rd[find_facility_name(incident)] + incident
for incident in incident_list]
To do the sort, you can use the ID string that we just prepended to the email message, rather than parsing to find the ID again:
combination.sort(key=lambda x: (x[0:3], get_date_of_incident(x)))
The 3 in the slice is based off of your example of "001" and "002" as the id values. If the actual ids are longer or shorter you'll need to adjust that.
So, here is what I think is going on. Please correct me if possible.
The 'incident_list' is a list of email strings. You go in and find the facility names in each email because you have an external dictionary that has the (key:value)=(facility id: facility name). From the dictionary, you can extract the facility id in this 'id_list'.
You combine the lists so that you get a list of strings [facility id + email,...]
Then you want it to sort by a tuple( facility id, date of incidence ).
It looks like you are searching for the facility id and the facility name twice. You can skip a step if they are the same. Then, the best way is to do it all at once with tuples:
incident_list = ['email1', 'email2',...]
unsorted_list = []
for email in incident list:
id = find_facility_id(email)
date = find_date_of_incident(email)
mytuple = ( id, date, id + email )
unsorted_list.append(mytuple)
final_list = sorted(unsorted_list, key=lambda mytup:(mytup[0], mytup[1]))
Then you get an easy list of tuples sorted by first element (id as a string), and then second element (date as a string). If you just need a list of strings ( id + email ), then you need a list with the last element of each tuple part
FINALLIST = [ tup[-1] for tup in final_list ]

Categories

Resources