Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
manipulating two lists
#1
Hi,

I do not understand why am i getting all the double usernames executing the code below:

existing_accounts = ["Marcis", "John", "Tim"]
new_accounts = ["Sarah", "Marcis", "Tim", "Marcis"]

for existing_account in existing_accounts:
	for new_account in new_accounts:
		if new_account == existing_account:
			print(new_account + " is already taken!")
			new_accounts.remove(new_account)
		else:
			print (new_account + " you are now registered.")
			existing_accounts.append(new_account)
			
print(existing_accounts)
print(new_accounts)
As the result i want only unique usernames in existing_account list.

Thanks.
Reply
#2
You don't need the outer loop at all (for existing acount....). Just loop over the new accounts and check if they are in existing accounts.

    if new_account in existing_accounts:
        # report they already exist
    else:
        # create new account.
Reply
#3
(Apr-15-2020, 08:42 PM)bowlofred Wrote: You don't need the outer loop at all (for existing acount....). Just loop over the new accounts and check if they are in existing accounts.

    if new_account in existing_accounts:
        # report they already exist
    else:
        # create new account.
Now I get this working but there are left two Marcis entries in the new users list after execution. How to tackle this?

existing_accounts = ["Marcis", "John", "Tim"]
new_accounts = ["Sarah", "Marcis", "Tim", "Marcis"]
for new_account in  new_accounts:
    if new_account in existing_accounts:
    	print(new_account + " is already taken!")
    	new_accounts.remove(new_account)
    else:
    	print (new_account + " you are now registered.")
    	existing_accounts.append(new_account)
    	new_accounts.remove(new_account)
			
print(existing_accounts)
print(new_accounts)
Reply
#4
The quick way is to change new_accounts into a set instead of a list; sets store unique values only.

existing_accounts = ["Marcis", "John", "Tim"]
new_accounts = ["Sarah", "Marcis", "Tim", "Marcis"]

for new_account in  set(new_accounts):
    if new_account in existing_accounts:
        print(new_account + " is already taken!")
        new_accounts.remove(new_account)
    else:
        print (new_account + " you are now registered.")
        existing_accounts.append(new_account)
        new_accounts.remove(new_account)
             
print(existing_accounts)
print(new_accounts)
Something to be aware of when iterating over lists: alterations to the list inside the loop can cause problems. For instance, if Tim did not have an existing account, he would likely not be listed in new_accounts at the end. This is due to the indices of the contents changing because of the removal of Marcis, but the index for the loop doesn't adjust accordingly. Remove Tim from existing_accounts and run it again; you should find a problem.
Reply
#5
Why would you care about the contents of that list? I would probably just ignore it and not look at it after the loop.

But the technical reason is that trying to remove elements from a list while iterating through that list is not allowed.

Don't do this:
for i in mylist:
    mylist.remove(i)
It confuses the iterator and you won't necessarily loop over everything properly.

You could make a copy of the list and then iterate over the copy.
for i in list(mylist):  # iterates over a copy
    mylist.remove(i)
Reply
#6
Removing items from the list you are iterating is bad. You can kind of do it if you start from the end and work backward, but it is far better to build a new list.
existing_accounts = ["Marcis", "John", "Tim"]
new_accounts = ["Sarah", "Marcis", "Tim", "Marcis"]

invalid_accounts = []
for account in new_accounts:
    if account in existing_accounts:
        invalid_accounts.append(account)
    else:
        existing_accounts.append(account)
             
print(existing_accounts)
print(invalid_accounts)

# If you want to put invalid accounts back in "new_accounts"
new_accounts[:] = invalid_accounts
Reply
#7
The reason to care is simple: this is a toy project. In a real project, the new user would be signed up and the iterative problem would preclude that. Plus, the OP is learning and needs to learn about those problems, why they happen, and how to work around them.
Reply
#8
(Apr-15-2020, 09:51 PM)stullis Wrote: The quick way is to change new_accounts into a set instead of a list; sets store unique values only.

existing_accounts = ["Marcis", "John", "Tim"]
new_accounts = ["Sarah", "Marcis", "Tim", "Marcis"]

for new_account in  set(new_accounts):
    if new_account in existing_accounts:
        print(new_account + " is already taken!")
        new_accounts.remove(new_account)
    else:
        print (new_account + " you are now registered.")
        existing_accounts.append(new_account)
        new_accounts.remove(new_account)
             
print(existing_accounts)
print(new_accounts)
Something to be aware of when iterating over lists: alterations to the list inside the loop can cause problems. For instance, if Tim did not have an existing account, he would likely not be listed in new_accounts at the end. This is due to the indices of the contents changing because of the removal of Marcis, but the index for the loop doesn't adjust accordingly. Remove Tim from existing_accounts and run it again; you should find a problem.

Thank you for your patience. Do I understand correctly, that when you changed the list to set where I had only one "Marcis" value to iterate through and remove from new_accounts. That is why I get the other "Marcis" value which is not removed from the new_accounts list?

I still do not understand how come I don't see "Marcis is already taken!" message in this code:
existing_accounts = ["John", "Tim", "Sarah", "Marcis"]
new_accounts = ["Sarah", "Marcis", "Tim"]
 
for new_account in  new_accounts:
    if new_account in existing_accounts:
        print(new_account + " is already taken!")
        new_accounts.remove(new_account)
    else:
        print (new_account + " you are now registered.")
        existing_accounts.append(new_account)
        new_accounts.remove(new_account)
and why am I seeing "Marcis" in the new_accounts list, when it should be removed when iterating through the loop.
Reply
#9
To see the problem, try running this code:
existing_accounts = ["John", "Tim", "Sarah", "Marcis"]
new_accounts = ["Sarah", "Marcis", "Tim"]
  
i = 0
while i < len(new_accounts):
    new_account = new_accounts[i]
    if new_account in existing_accounts:
        print(new_account + " is already taken!")
        new_accounts.remove(new_account)
    else:
        print (new_account + " you are now registered.")
        existing_accounts.append(new_account)
        new_accounts.remove(new_account)
    i += 1
    print(i, new_accounts)
Output:
Sarah is already taken! 1 ['Marcis', 'Tim'] Tim is already taken! 2 ['Marcis']
Removing Sarah from new_accounts makes Marcis the first element in the list. The second time through the loop looks at new_accounts[1], and that is Tim. We skipped Marcis because we change the list we are using to iterate.

One of many ways to get around this problem is create a copy of the list to use for the iterator.
existing_accounts = ["John", "Tim", "Sarah", "Marcis"]
new_accounts = ["Sarah", "Marcis", "Tim"]
  
for new_account in new_accounts[:]:  # This iterates over a copy of new_accounts
    if new_account in existing_accounts:
        print(new_account + " is already taken!")
    else:
        print (new_account + " you are now registered.")
        existing_accounts.append(new_account)
    new_accounts.remove(new_account)
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Split dict of lists into smaller dicts of lists. pcs3rd 3 2,387 Sep-19-2020, 09:12 AM
Last Post: ibreeden
  Manipulating data from a CSV EvanS1 5 2,735 Jun-12-2020, 05:59 PM
Last Post: perfringo
  Manipulating index value, what is wrong with this code? Emun 1 1,761 Feb-05-2020, 07:18 AM
Last Post: perfringo
  Manipulating the filename of an output script mckinneycm 4 11,904 Jan-15-2020, 07:29 PM
Last Post: mckinneycm
  Manipulating Excel with Python. Spacely 2 3,645 Jun-25-2019, 01:57 AM
Last Post: Dequanharrison
  Manipulating CSV Prince_Bhatia 1 1,967 Apr-25-2019, 11:55 AM
Last Post: Gribouillis
  sort lists of lists with multiple criteria: similar values need to be treated equal stillsen 2 3,293 Mar-20-2019, 08:01 PM
Last Post: stillsen
  Reading and manipulating csv Prince_Bhatia 11 5,095 Mar-14-2019, 11:40 AM
Last Post: Larz60+
  Manipulating an Excel Workbook Stanimal 4 3,011 Jan-18-2019, 11:03 PM
Last Post: Stanimal
  Manipulating Binary Data arsenal88 10 8,654 Apr-25-2017, 02:30 PM
Last Post: snippsat

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020