this is a quick one. Suppose I got a multidimensional list of class objects, named table, and I need to access the class attribute .name.
I don't want to use nested loops, and of course to print this, I need to use format().
for i in range(3):
print '{0} - {1} - {2}'.format(*table[i].name)
Obviously that didn't work. As well as (*table[i]).name. I need to be able to access .name for each class object in the table[i] list. Mind if you put me to the right direction? Thanks in advance.
{arg_name.attribute_name} also works:
for row in table:
print(' - '.join('{0.name}'.format(elt) for elt in row))
Like this, for example:
for row in table:
print '{0} - {1} - {2}'.format(*[x.name for x in row])
I don't want to use nested loops
This is silly. To iterate over each element of a multidimensional array, you need to use nested loops. They may be implicit (map or a list comprehension) but that doesn't mean they're not there! The following is going to be much neater and cleaner than anything with map or a nasty format unpacking.
for row in table:
for elt in row:
print <...>
If you really want to know how to use your method:
import operator
for row in table:
print '{0} - {1} - {2}'.format(*map(operator.attrgetter('name'), row))
Tell me that's not messy and unclear compared to the above, not to mention the fact that you've hardcoded in the magic constant 3 -- what if you want to change to a 4x4 table?
Related
I'm doing the following, and it works, but it is not elegant. I'm wondering if anyone has any insight as to a prettier way to do this.
Let's say I have n booleans that the user will set to be true or false. For each boolean, there is an associated function do_something that takes as input the next unprocessed column in a multidimensional list called myList. The following code does just this:
i=0
if boolean1:
do_something1([a[i] for a in myList])
i+=1
if boolean2:
do_something2([a[i] for a in myList])
i+=1
if boolean3:
do_something3([a[i] for a in myList])
i+=1
...
Even though it works, something in me tells me that there is a much more elegant way to do it. It seems like it might be better to push the columns onto a queue and then pop them off when one of the booleans is satisfied. But that seems like a whole lot of overhead. Does anyone have any suggestions?
If you can put the booleans and functions into a list, you could do:
processing = zip(booleans, functions)
for i, action in enumerate([p for (b,p) in processing if b]):
action([a[i] for a in myList])
Transpose myList first (flip rows into columns) and then iterate over it.
for boolean, row in zip(booleans, zip(*myList)):
if boolean:
process(row)
The inner zip is part of the idiom zip(*l), which transposes a list.
Something like this?
processing = ((boolean1, do_something1), (boolean2, do_something2),
(boolean3, do_something3))
i=0
for b, process in processing:
if b:
process[(a[i] for a in myList])
i+=1
I have a list of instances of a class A
class A:
def __init__(self,ox,oy):
self.x=ox
self.y=oy
list1=[A(3,0),A(5,0),A(7,3),......]
Now I need to find out the instance in the list which has y' as non-zero - and apply that value to all the other members in the list.
It is given that only one unique member will have y as non-zero.
With the usual for-loop we would need to iterate the list twice - with or without comprehension.
Is there a way to achieve this any better.
I have not used filter and map much but feel there may be a better option.
Help is appreciated.
No, there isn't. At least two loops would be required no matter how it was implemented.
import numpy
a = numpy.array([[3,0],[5,0],[7,3]])
zero_mask = a[:,1] == 0
a[zero_mask] = a[~zero_mask][0]
unfortunately it does not use your A class ...
Hy!
As a complete beginner to python I wonder how I fetch a tuple-element inside a tuple of tuples - i.e. the result of
results=cursor.fetchall()
gives a tuple
((row1_value1,row1_value2,...),(row2_value1,row2_value2..),)
I know that
for id in results:
print id
or
results [i]
accesses each row as a whole.
But how do I directly access a tuple - value inside the tuple, i.e. row2_value3 ???
I helped myself with the following code, but isnĀ“t there a possibility to give a exact "adress", such as
results [i,sub-i] ??
for id in results:
a=results[i]
i=0
for x in a:
print a[i]
i+=1
I want to use fetchall, just to learn how to do things in python- i want to have the whole datbase in python and work with that.
Thanks a lot!
results[0][1]
accesses the second (1) element from the first (0) row (row1_value2 in your case). The lists in Python are 0-indexed.
The same way, row2_value3 is results[1][2]
You can just do results[row][field].
Have table want to use numpy to slice into sections
table = ['212:3:0:70.13911:-89.85361:3', '212:3:1:70.28725:-89.77466:7', '212:3:2:70.39231:-89.74908:9', '212:3:3:70.48806:-89.6414:11', '212:3:4:70.60366:-89.51539:14', '212:3:5:70.60366:-89.51539:14', '212:3:6:70.66518:-89.4048:16']
t = np.asarray (table, dtype ='object')
Want to use numpy to slice all........ 212:3:0, 212:3:1 as k.
Want all '212:3:0:70.13911:-89.85361:3','212:3:1:70.28725:-89.77466:7' as v
into a dictionany dict (k,v). I dont want to use a for-loop to do this...
I have done this as for loop its slow.
NOTE: the row has ":", but the ":" does mean the dict ':'.
Basics of dict comprehensions
To convert something into a dict, you need to make it into an iterable that generates 2-sequences (anything that generates a sequence of two elements), like [[1,2],[3,4]] or [(1,2),(3,4)] or zip([1,2,3,4], [5,6,7,8]))
E.g.
>>> mylst = [(1,2), (3,4), (5,6)]
>>> print dict(mylst)
{1:2, 3:4, 5:6}
so you need to split each of your strings in such a way that you produce a
tuple. say you've already written a function that does this, called
split_item that takes in a two strings and returns a tuple. You could then
write a generator expression like the following so that you don't need to load
everything into memory until you create the dict.
def generate_tuples(table):
length = len(table)
for i in range(1, length - 1):
yield split_item(table[i-1], table[i])
then just call the dict builtin on your generator function.
>>> dict(generate_tuples(table))
Since you say you already wrote this with a for-loop, I'm guessing you already have a split_items function written.
Making it fast
Here's a guide to high-performance Python, written by Ian Ozsvald, that can help you experiment with other ways to increase the speed of processing. (credit to #AndrewWalker 's SO post here)
Is this what you're after?
dict( (t.rsplit(':', 3)[0], t) for t in table ) )
.append
Function adds elements to the list.
How can I add elements to the list? In reverse? So that index zero is new value, and the old values move up in index?
What append does
[a,b,c,d,e]
what I would like.
[e,d,c,b,a]
Thank you very much.
Suppose you have a list a, a = [1, 2, 3]
Now suppose you wonder what kinds of things you can do to that list:
dir(a)
Hmmmm... wonder what this insert thingy does...
help(a.insert)
Insert object before index, you say? Why, that sounds a lot like what I want to do! If I want to insert something at the beginning of the list, that would be before index 0. What object do I want to insert? Let's try 7...
a.insert(0, 7)
print a
Well, look at that 7 right at the front of the list!
TL;DR: dir() will let you see what's available, help() will show you how it works, and then you can play around with it and see what it does, or Google up some documentation since you now know what the feature you want is called.
It would be more efficient to use a deque(double-ended queue) for this. Inserting at index 0 is extremely costly in lists since each element must be shifted over which requires O(N) running time, in a deque the same operation is O(1).
>>> from collections import deque
>>> x = deque()
>>> x.appendleft('a')
>>> x.appendleft('b')
>>> x
deque(['b', 'a'])
Use somelist.insert(0, item) to place item at the beginning of somelist, shifting all other elements down. Note that for large lists this is a very expensive operation. Consider using deque instead if you will be adding items to or removing items from both ends of the sequence.
Using Python's list insert command with 0 for the position value will insert the value at the head of the list, thus inserting in reverse order:
your_list.insert(0, new_item)
You can do
your_list=['New item!!']+your_list
But the insert method works as well.
lst=["a","b","c","d","e","f"]
lst_rev=[]
lst_rev.append(lst[::-1])
print(lst_rev)
Here's an example of how to add elements in a list in reverse order:
liste1 = [1,2,3,4,5]
liste2 = list()
for i in liste1:
liste2.insert(0,i)
Use the following (assuming x is what you want to prepend):
your_list = [x] + your_list
or:
your_list.insert(0, x)