-3

I am trying to print out just the dict values inside a list in python.

car_object = {}
    cursor = self._db.execute('SELECT IDENT, MAKE, MODEL, DISPLACEMENT, POWER, LUXURY FROM CARS')
    for row in cursor:
       objectname = 'Car_Object_'+str(row['IDENT'])
       # print (objectname)
       car_object[objectname] = Cars(ident = row['IDENT'], make = row['MAKE'], model = row['MODEL'], disp = row['DISPLACEMENT'], power = row['POWER'], luxury = row['LUXURY'])
       print(objectname, car_object[objectname])
        #print(row['IDENT'], row['MAKE'], row['MODEL'], row['DISPLACEMENT'], row['POWER'], row['LUXURY'])

       yield dict(row)

So it is printing:

Car_Object_meA160 {'power': 55, 'ident': 'meA160', 'model': 'A160 CDI', 'disp': 1.7, 'make': 'mercedes', 'luxury': 'N'}
Car_Object_meA190 {'power': 92, 'ident': 'meA190', 'model': 'A190', 'disp': 1.7, 'make': 'mercedes', 'luxury': 'Y'}
Car_Object_meA210 {'power': 103, 'ident': 'meA210', 'model': 'A210 EVO', 'disp': 1.7, 'make': 'mercedes', 'luxury': 'Y'}

...and so on I want to be able to print it like so:

                      IDENT         MAKE         MODEL        DISP       POWER     LUX
Car_Object_meA160     meA160       mercedes      A160 CDI     1.7          55      N
Car_Object_meA190     meA190       mercedes      A190         1.7          92      Y
Car_Object_meA210     meA210       mercedes      A210 EVO     1.7          103     Y

So i want to be able to print just the values....with the headers ordered a certain way. Is it possible to do this? Thanks.

DSM
  • 342,061
  • 65
  • 592
  • 494
engr007
  • 51
  • 4
  • 12
  • If you don't know how to do this, then you should learn python first. There are tonnes of resources on the internet on how to format print. Python makes it ridiculously easy to "printf". – mmtauqir Mar 01 '13 at 14:55
  • I have scoured the internet on how to do this, and can't figure it out. – engr007 Mar 01 '13 at 15:00
  • Since you are "getting only one row" with all the answers provided here, how many rows do you get if you simply put a `print` statement in your `for` loop? You are using a generator function. Are you sure you read all the values from the generator, or only the first one? And why are you using a generator in the first place? – tobias_k Mar 01 '13 at 16:15
  • @tobias_k: I get all rows when I do this: `print(objectname, car_object[objectname])` . I'm using a generator, because that's what we're required to use for the project...I know not the best thing, but someone wants it this way. – engr007 Mar 01 '13 at 16:27
  • Figured it out at last. I made a get_Variable function in the Cars class and am calling `car_object[objectname].getVariable('model'), car_object[objectname].getVariable('make') `.....etc. This works and is a much simpler solution. Thank you. – engr007 Mar 01 '13 at 18:38

4 Answers4

1

The tricky part is aligning the several table entries and the table headers. For this, we first have to find out how long the longest entry in each column is. pad then can be used to add a number of padding spaces to the given string.

fields = ["ident", "make", "model", "disp", "power", "luxury"]
max_len = {"name": max(map(len, car_objects)) + 1}
for f in fields:
    max_len[f] = max(map(len, [f] + [str(car[f]) for car in car_objects.values()]))
pad = lambda s, f: str(s).ljust(max_len[f])

Now, we can print the headers and the several entries in car_objects using the pad function defined above.

print pad("", "name") + " ".join(pad(f.upper(), f) for f in fields)
for name, car in car_objects.items():
    print pad(name, "name") + " ".join(pad(car[f], f) for f in fields)

This should work, assuming that the elements of car_objects are Python dictionaries. If not, try to replace car[f] with getattr(c, f) in the above code.

Update: Of course, perfectly aligning the columns of the table only works if you know all the rows before actually printing them. If you have to print them while still reading entries from the database, you have to 'guess' by how many spaces to pad the strings so they are nicely aligned in a table. This makes everything much simpler. Just put this line before your for loop for printing the table headers:

print (" " * 20) + " ".join(f.upper().ljust(10) for f in fields)

And this line inside your loop, before the yield:

print name.ljust(20) + " ".join(str(getattr(car, f)).ljust(10) for f in fields)

str.ljust(n) is a standard string function that return the string aligned to the left within a total width of n characters. There are similar functions for aligning right and center alignment: rjust and center. And since your cars seem to be instances of some class, you can use the builtin function getattr(<object>, <attribute name>) to retrieve the individual attributes of the cars (similar to your getVariable method).

For more on string formatting, take a look a this Python documentation page.

tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • only brings back 1 row `for row in cursor: objectname = 'Car_Object_'+str(row['IDENT']) car_object[objectname] = Cars(ident = row['IDENT'], make = row['MAKE'], model = row['MODEL'], disp = row['DISPLACEMENT'], power = row['POWER'], luxury = row['LUXURY']) fields = ["ident", "make", "model", "disp", "power", "luxury"] max_len = {"name": max(map(len, car_object)) + 1} for f in fields: max_len[f] = max(map(len, [f] + [getattr(car,f) for car in car_object.values()])) pad = lambda s, f: s + (" " * (max_len[f] - len(s)))` – engr007 Mar 01 '13 at 16:02
  • @user2096860 Well, you have to insert the code after all the cars have been added to `car_objects`, i.e. after the `for` loop; otherwise how to align the rows? – tobias_k Mar 01 '13 at 16:11
0

Try this:

#print your header labels first                                                                                                                       
d = {'power': 55, 'ident': 'meA160', 'model': 'A160 CDI', 'disp': 1.7, 'make': 'mercedes', 'luxury': 'N'}
# this is for each car                                                                                                                                
headers = ['ident', 'make', 'model', 'disp', 'power', 'luxury'] # change this order if you   want different order                                       
values = [d[h] for h in headers]
print("{0:12}{1:12}{2:12}{3:12}{4:12}{5:12}".format(values[0], values[1], values[2], values[3], values[4], values[5]))
zz3599
  • 647
  • 5
  • 20
  • @zz3599...this throws an error 'values = [d[h] for h in headers] TypeError: 'Cars' object is not subscriptable' – engr007 Mar 01 '13 at 14:59
  • that means the Cars object is not a dictionary. You should be using what I gave you for each row, not the entire list. – zz3599 Mar 01 '13 at 15:01
  • yes, if I only put a single row of data in d it works...how to make it more generic for all the rows I'm printing though? I have 30+ of these? – engr007 Mar 01 '13 at 15:06
  • `headers` list should only be declared once. You put the rest inside the for loop, which will only process one row at a time. – zz3599 Mar 01 '13 at 15:14
  • I have this now: `def __iter__(self): headers = ['ident', 'make', 'model', 'disp', 'power', 'luxury'] car_object = {} cursor = self._db.execute('SELECT IDENT, MAKE, MODEL, DISPLACEMENT, POWER, LUXURY FROM CARS') for row in cursor: objectname = 'Car_Object_'+str(row['IDENT'])` – engr007 Mar 01 '13 at 15:18
  • `car_object[objectname] = Cars(ident = row['IDENT'], make = row['MAKE'], model = row['MODEL'], disp = row['DISPLACEMENT'], power = row['POWER'], luxury = row['LUXURY']) d = car_object[objectname] print(d) values = [d[h] for h in headers] print("{0:12}{1:12}{2:12}{3:12}{4:12}{5:12}".format(values[0], values[1], values[2], values[3], values[4], values[5]))` .....still 1 row printing – engr007 Mar 01 '13 at 15:19
0

Try the following... I tested it with dictionaries so I access the attributes you have as car_object[obj][key.lower()]. I can't say without looking at your Cars class, but you should probably replace it with something like car_obj[obj].__getattribute__(key.lower())

car_object = {}
car_object['Car_Object_meA160'] = {'power': 55, 'ident': 'meA160', 'model': 'A160 CDI', 'disp': 1.7, 'make': 'mercedes', 'luxury': 'N'}
car_object['Car_Object_meA190'] = {'power': 92, 'ident': 'meA190', 'model': 'A190', 'disp': 1.7, 'make': 'mercedes', 'luxury': 'Y'}
car_object['Car_Object_meA210'] = {'power': 103, 'ident': 'meA210', 'model': 'A210 EVO', 'disp': 1.7, 'make': 'mercedes', 'luxury': 'Y'}

keys = ['IDENT', 'MAKE', 'MODEL', 'DISP', 'POWER', 'LUXURY']
fmt ='{:>10}' * (len(keys) + 1)
print ' '*len('Car_Object_meA160'), fmt.format('', *keys)

for obj in car_object:
    print obj, fmt.format('', *([car_object[obj][key.lower()] for key in keys]))
Dhara
  • 6,587
  • 2
  • 31
  • 46
  • I am only getting 1 row with this....The above is just an example...I have about 30 some rows generated from reading the data from the db. – engr007 Mar 01 '13 at 15:14
  • the for loop over car_object should find all the "rows". Does running car_object.keys() output all 30 keys? – Dhara Mar 01 '13 at 15:40
  • is there a way for you to retype the method, please?...i think i'm definitely missing something simple in here...since it is correctly bringing back 1 row. – engr007 Mar 01 '13 at 16:04
  • Does running car_object.keys() output all 30 keys? YES. – engr007 Mar 01 '13 at 16:08
-1

Yes. Here's a quick function that takes a list and prints out what you want.

def output(cars):
    print "          IDENT        MAKE        MODEL        DISP        POWER"
    for i in cars:
        print type(i),"    ",i[ident],"   ",i[make],"   ",i[model],"   ",i[disp],"   ",i[power]

It should print out as many cars that you put it. although i am not positive about the spacing.

Jroosterman
  • 408
  • 4
  • 11