views:

94

answers:

3

I have something like the follwing.

A person having many colors of cars of the same model belonging to some state.

I have designed a person class as having attributes person name, car model, car year, car state, and car color as attributes. And color should be a list as a person can have many cars of different colors but of the same model.

Now how do I find and print 2 different people who have same model of car and same color of car but belong to different states in object oriented terms?

I am new to Python.

While inserting color into the person object how do I insert into the list and how do I retrieve from the list? I know how to do it for an attribute, but I am a little confused about list operations.

The data can be like this:

person1 ford   [red,blue,yellow] new-york
person2 honda  [red,blue]        new-york
person3 ford   [red,grey]        california
person4 ford   [red]             california
person5 honda  [red]             new-york

Now my result should only be:

[(person1,person5)]    (same model car,same color, different state)
+2  A: 

You might want to model state and car separately from person. Then, each person can have a list of cars, and live in a state (or even a list of states, depending on your model). These are has-a relationships. It will also allow you to subclass car later and make sportsCar later, if you want.

eruciform
+1  A: 

You wanted to know a little about list manipulation:

$ python
Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> l=[]
>>> l.append("honda")
>>> l.append("ford")
>>> l
['honda', 'ford']
>>> l[0]
'honda'
>>> l.pop(0)
'honda'
>>> l.pop(0)
'ford'
>>> l.pop(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: pop from empty list

If you want to find several persons with matching attributes, you could do some iteration (represented here in some psuedo-code, because I think focussing on the algorithm is more useful than focussing on the python to make it happen):

results = []
foreach p1 in [list of people]
    foreach p2 in [list of people]
        next if p1 == p2
        next if p1.state == p2.state
        next unless p1.car == p2.car
        foreach c1 in p1.colors
            foreach c2 in p2.colors
                results.append((p1,p2)) if c1 == c2

This code compares pairs of people. It doesn't compare a person against themself. It doesn't compare people who live in the same state because you asked for ".. but belong to different states". So let's filter those same-state people out. It compares only people who own the identical kind of car. (If people owned different types of cars, then you'd just add two more nested for loops.) Then it notes the pairs of people that have the same color of car.

There's a potential bug in this algorithm: it'll report [(person1, person2), (person2, person1)]. So entries are duplicated. It's possible to amend the algorithm to search just the upper or lower triangle of people if you don't want this duplication:

results = []
for i=0; i<people.last_index-1; i++
    for j=i+1; j<people.last_index ; j++
        p1 = people[i] ; p2 = people[j]
        next if p1.state == p2.state
        next unless p1.car == p2.car
        foreach c1 in p1.colors
            foreach c2 in p2.colors
                results.append((p1,p2)) if c1 == c2

Note we can remove the next if p1 == p2 check because we explicitly cannot get i == j. j is defined to start with i+1.

sarnold
Thanks so much...That helped a lot.
jerrygo
+2  A: 

There are a bunch of ways to do this. If you have a lot of data then I'd recommend that you go ahead and tackle a database based implementation using python's built-in sqlite support (which is actually not that hard). A database engine is purpose built for searching. You would need two tables since you can have multiple colors per person. The person table would have the following columns: id, name, model, state. The colors table would have: personid, color. The personid column would contain the id number that the row in the color table corresponds to. You can then have multiple rows in the color table with the same personid value (which is the database version of a list). sqlAlchemy is a library to help implement a database using python objects which you may find more appropriate with what you are trying to do. The sqlAlchemy ORM Tutorial walks you through working with an sqlite database with two tables (users, addresses) that are very similar to what you would need.

Now if you want stick with python classes alone you are going to have to have a list of people instances and iterate through them all looking for matches. A handy simplification for your color matching is to convert the color lists to sets and do an intersection.

>>> s1 = set(['red','blue','yellow'])
>>> s2 = set(['red','blue'])
>>> s1.intersection(s2)
set(['blue', 'red'])

A shortcut for your iteration through the list of people instances is to use python's itertools library and use the permutations generator.

from itertools import permutations
people = ['p1', 'p2', 'p3']
for p1, p2 in itertools.permutations(people,2):
    print p1, p2

p1 p2
p1 p3
p2 p1
p2 p3
p3 p1
p3 p2

Hopefully this is enough to help you along your way. Rereading your question it looks like you may need to do more reading on programming in python. But to address your question about lists here is a little bit of code that may help you out.

class Person(object):
    def __init__(self, name, model, colors, state):
        self.name = name
        self.model = model
        self.colors = colors
        self.state = state

p1 = Person('p1', 'ford', ['red', 'blue'], 'new-york')
p2 = Person('p2', 'honda', ['red', 'blue'], 'new-york')

persons = [p1, p2]
  # or
persons = []
persons.append(p1)
persons.append(p2)

p1.color.append('yellow')
  # or
persons[0].color.append('yellow')
JT
Thank you for replying. Was very helpful.
jerrygo