Python list question

Thread Starter

geoffers

Joined Oct 25, 2010
308
Hi all,

Probably a simple one for someone!
I'm abusing Python to sort my sheep for breeding (prevent inbreeding).

I have a list which holds the ids of all the ewes, this id can be used by the program to look up the sire, dam, grandsires and grand dams from my sheep database.

As I check for relationship with the rams I'm going to use, the ewes ID is removed from the breeding list if it isn't related.

I use the list.remove(ewe) method to remove the ID from the list.

This works fine until I get to 11 elements left in the list the it throws out of the loop.

The loop is

for ewe in ewelist:

(Code to check for relationship)

ewelist.remove(ewe)
ramgroup.append(ewe)

Have I got something obviously wrong here? I can post full code when I'm at the computer but I'm not great at Python so thought it could be obvious :)

Cheers Geoff
 

WBahn

Joined Mar 31, 2012
24,850
How does it throw out of the loop? By failing the loop test? What is the loop test?

Use a toy database and print the contents of the list as things progress.
 

joeyd999

Joined Jun 6, 2011
4,268
I'm not a python programmer, so I cannot help you directly.

But, if it were my project, I'd use a database (in my case, MySQL) to store all the animal data.

Then, I'd write a (relatively simple) SQL query to generate a report of acceptable pairings. The database does the heavy lifting -- no loops required.

I assume Python easily integrates various databases, and your Python code could be the front end to your overall application.
 

WBahn

Joined Mar 31, 2012
24,850
I only use Python occasionally, but in general you have to be careful removing elements from a list while iterating over it. This may help:
https://stackoverflow.com/questions/1207406/how-to-remove-items-from-a-list-while-iterating

From that thread, to show you what may go wrong with your approach, the first example here is essentially your method:
View attachment 179985
Very good catch.

@geoffers: Do you see what is happening?

When you iterate over the list using a for-each construct, it is basically walking across the memory locations (though that is likely just the effect an not the actual mechanism) so say you are at the third item in the list. If you delete it, the fourth item in the list becomes the new third item but then your iterator moves on to the fourth item (which used to be the fifth item). The original fourth item thus gets skipped completely.

In the second case, a new list is created that is a copy of the original list. Then the copy is iterated over but never changed. Each item thus gets checked and, if necessary, the corresponding item with the same value is removed from the original list.
 

Thread Starter

geoffers

Joined Oct 25, 2010
308
Thanks everyone!

That makes perfect sense, in effect the 'counter' is pre incremented before my code has run.

There's always a catch!

Joey, my database at the moment just contains the ewes parents, I query it to get their ID, then query it again to get with that data to get grandparents ID.

I put that in a list and loop through checking for any matches with a potential rams ID, parentage and grandparents.

At the moment I'm not sure my database skills are up to doing that in SQL but I'm curious, is it possible without building a new database containing grandparents as a entry?

Cheers Geoff

PS the rams are now with the ewes with no inbreeding going on :cool:
 

WBahn

Joined Mar 31, 2012
24,850
At the moment I'm not sure my database skills are up to doing that in SQL but I'm curious, is it possible without building a new database containing grandparents as a entry?
Yes. In fact, you do not want to add a grandparents entry. Having the ID of the two parents is sufficient. With that, the information necessary to figure out who the grandparents are is there (and you can go back as many generations as you have data for). If you add a grandparents field, now you have two ways to determine who the grandparents are -- directly from that ewe's record or from the records of that ewe's parents. That means that you have redundant data in the data base and that is usually a bad thing. What if the two results don't agree? What if then one part of your application gets the information one way while another part gets it the other? Big problems lay down that path.
 

RAMBO999

Joined Feb 26, 2018
92
Put simply:

The iteration drops out of the loop because "ewe in ewelist" returns a logical false.

In other words whatever the value of ewe is at that time that value does not exist in ewelist.

There are several ways you can debug this if you think there is a bug.

The print statement comes in handy. print(ewe)
 
Top