0

I have a very large list of objects (the things that you can make with Classes, yeah?). I want to go through this list and remove objects if they have certain values. I'm going to then use the sorted list to pick out random elements and use them for other things.

Should I be using dictionaries or arrays or something instead of objects and lists? I am very new to this, I am sorry if it is very simple or I've done something wrong.

Example:

class Person:
    def __init__(self, name, gender, otherVar, otherVar2):
        self.name = name
        self.gender = gender
        self.otherVar = otherVar
        self.otherVar2 = otherVar2
        ## also more variables if that makes a difference

John = Person("John", boy, otherVar, otherVar2)
Jane = Person("Jane", girl, otherVar, otherVar2)   ## etcetera


myList = [John, Jane, Mary, Derek, Bob, Sue]
simpleThingThatIdoNotUnderstand():                 ## removes all the 
                                                   ## girls
myList = [John, Derek, Bob]

I understand I need some sort of loop through the list (though there are so many ways, I am not sure which one will work), but how do I reference a value of an object in the list? Like 'if gender = girl, remove item'

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
janedoe
  • 13
  • 1
  • The proper thing to use in this case is "list comprehension" ([See this other answer of mine with a somewhat similar use-case](https://stackoverflow.com/a/37869704/227884)). However, you could get it done using a for-loop and an if-condition too. – UltraInstinct Oct 22 '18 at 23:43
  • `boys = [person for person in myList if person.gender == 'boy']` or `boys = list(filter(lambda p: p.gender == 'boy', myList))` – aydow Oct 22 '18 at 23:43
  • You generally can't delete items in a list while iterating its elements. This means that to do what you want requires creating a new list with just the elements in it you want to keep. – martineau Oct 22 '18 at 23:46
  • To reference attributes of an element in the list, just use `element.name`, `element.gender`, etc. When writing more generic code, you can do things like e.g. `attr_name="gender"` followed by `value = getattr(element, attr_name)`. – martineau Oct 22 '18 at 23:59

4 Answers4

1

There are a few ways you can do this, some faster or less code than others.

The simplest is to iterate through the entire list, examine if the item matches some criteria, and then remove that item. Particularly because you're applying a condition to your entire set of people.

In your example, this may look like:

# removes all people of the specified gender
def removePeopleByGender(people, gender):
   output = []

   for person in people:
       # assumes person.gender and gender are the same data type
       if (person.gender != gender):
           output.append(person)

   return output

Generally, dictionaries are preferred for (key, value) pairings in which you'll have a set of keys or a specific key and are trying to do quick lookups. They're heavily optimized for lookups O(1), but use a bit more memory.

Daniel Dobalian
  • 3,129
  • 2
  • 15
  • 28
0

This will make a new list of boys:

boys = [person for person in myList if person.gender == boy]

It's better to make a new list rather than try to remove objects from the list.

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
  • why is it better to create a new list? – aydow Oct 22 '18 at 23:46
  • 1
    Because mutating the old list can cause unintended effects if other parts of the program are still using the list. – Ned Batchelder Oct 22 '18 at 23:47
  • 1
    @aydow: Also mutating the list while iterating over it can mess up the loop doing the iteration—it might skip elements for example. See [How to modify list entries during for loop?](https://stackoverflow.com/questions/4081217/how-to-modify-list-entries-during-for-loop) – martineau Oct 22 '18 at 23:50
0

There are a few different ways to do this, depending on what you want to do with the items that match your conditions (in this case, the objects corresponding to girls). Given the list you're starting with:

myList = [John, Jane, Mary, Derek, Bob, Sue]

the most straightforward thing to do is to build another list that contains only the girls. There is a structure called a list comprehension which is well suited for this purpose:

new_list = [<expression> for <variable> in <original_list> if <condition>]

What this does is go through each element of <original_list>, temporarily sets <variable> to that element, tests <condition> to see whether it's true, and if so, it evaluates <expression> and puts it in the new list. It does exactly the same thing as this code:

new_list = []
for <variable> in <original_list>:
    if <condition>:
        new_list.append(<expression>)

except that it's more compact code that's easier for experienced Python programmers to read.

In your case:

  • <original_list> is myList
  • <variable> can be any Python identifier; let's say person
  • <condition> is going to be true if the person is a girl, which means person.gender == girl
  • <expression> is just person itself, since you just want the same object from the original list rather than some attribute of it or a function of it or some such thing

I'll leave it to you to substitute these components into the original list comprehension.

David Z
  • 128,184
  • 27
  • 255
  • 279
0

Using the classic for item in list: loop alone won't do the trick, as you can't remove elements from the list inside that loop.

First a would say you define a function that takes a Person and returns true if it should stay in the list or false if it should me removed. Let's suppose you name that function keep_person. After that, you can use one of these methods:

Using the filter function (recommended):

myList = filter(keep_person, myList)

Or this way, if you prefer good old loops:

people_to_remove = []
for person in myList:
    if not keep_person(person):
        people_to_remove.append(person)

for person in people_to_remove:
    myList.remove(person)

Of course, there are many other ways to do it.

Pablo Paglilla
  • 366
  • 2
  • 5