I want to loop through the list and extract the values.
The only algorithm I could think of is:
>>> for i in l:
... u = None
... try:
... (k, v) = i
... except ValueError:
... (k, u, v) = i
... print k, u, v
---------
1 None 2
3 4 5
6 None 7
-------------
But, this algorithm doesnt look very beautiful - like say -> for k, u,
v in L:
Can anyone suggest a better algorithm to get the values?
for i in l:
u = None
if len(i) == 2:
k, v = i
else:
k, u, v = i
Best I could come up with.
Alternatively:
def mangle(i):
if len(i) == 3:
return i
k, v = i
return k, None, v
for i in l:
k, u, v = mangle(i)
I'm sure there is a clever one liner using the Python 2.5 ternary
expression syntax. On the other hand I'm not sure it would be very
readable, so a straightforward (if less clever) solution is probably
better.
Michael
--
http://www.ironpythoninaction.com/
for i in L:
if len(i) == 2:
k, v, u = i + (None, )
else:
k, u, v = i
print k, u, v
regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/
Fuzzyman wrote:
> I'm sure there is a clever one liner using the Python 2.5 ternary
> expression syntax. On the other hand I'm not sure it would be very
> readable, so a straightforward (if less clever) solution is probably
> better.
that would be something like this (using a generator)
L = [(1, 2), (3, 4, 5), (6, 7)]
g = ( ((e[0],None,e[1]) if len(e)==2 else (e[0],e[1],e[2])) for e in L)
for elem in g:
print elem
So long,
Markus
P.S: No, I don't consider that more readable than your example ;-)
--
"Hacking is like having sex: you get in, you get out and you hope that you
did not leave anything which can be traced back to you" - Unbekannt
complement = lambda t: (t[0], None, t[1]) if len(t) == 2 else t
for k, u, v in map(complement, L):
print k, u, v
One way to avoid explicit checks on tuple size (but making the code a
bit less clear and probably slower):
for i in l:
k, v, u = (i[:3]+(None,))[:3]
...
Ciao
-----
FB
> g = ( ((e[0],None,e[1]) if len(e)==2 else (e[0],e[1],e[2])) for e in
> L)
If this isn't proof of Python's versatility, I don't know what is. In
one line it can mimic both Lisp and Perl. Sweet.
:)
/W
--
My real email address is constructed by swapping the domain with the
recipient (local part).
Just a note: this isn't really an algorithm problem. ;)
It's more of a grammar obstruction.
To make your code more simple, it would be nice if the assignment
operator would return, "None," in the case where there are too few
values to unpack from the right-operand of the assignment operator.
Aside from the typical workarounds that first came to mind, I started
wondering whether it was possible to expose the problem and solve it
directly.
Sadly, it appears to be non-trivial (or at least, well hidden from the
unwashed masses).
I'd be really curious if the unpacking machinery were exposed to the
developer. I started poking around the operator and types modules, but
the implementation isn't obvious. What methods are being called on the
operands by the assignment operator in the following statement:
a, b, c = some_tuple
I'm sorry if this line of inquiry is not very pythonic; but one is
curious if this is some python magic happening here. After using the
idiom for years I hadn't really thought about it much until recently.
Others have suggested messy ways to code what you're asking. At another
level, that list format seems like a code smell. You may be better off
organizing the program so that
L = [(1, None, 2), (3, 4, 5), (6, None, 7)]
after which unpacking becomes trivial.
> for i in l:
> u = None
> if len(i) == 2:
> k, v = i
> else:
> k, u, v = i
That's the best solution I have seen in this thread so far (but I
suggest to improve indents and use better variable names). In
programming it's generally better to follow the KISS principle.
Bye,
bearophile
Very true. +1
If this is part of a real program, instead of an exercise, you should
fix the code that creates this list of tuples so that they have a
uniform length of 3. And if the third element is missing, it should be None.
This saves lots of trouble later on.
-- Gerhard
Looks like the extended iterable unpacking feature of Python 3.0,
described in PEP 3132, comes to the rescue here:
>>> L = [(1, 2), (3, 4, 5), (6, 7)]
>>> for i in L:
... k, *u, v = i
... print(k, u, v)
...
1 [] 2
3 [4] 5
6 [] 7
--
Ned Deily,
n...@acm.org
for i in L:
k, u, v= i[ 0 ], i[ 1 ], i[ -1 ]
if len( i )== 2: u= None
tuples = [(1, 2), (3, 4, 5), (6, 7)]
def triple_or_pair(seq):
u = None
try:
k, u, v = seq
except ValueError:
k, v = seq
return k, u, v
for k, u, v in [ triple_or_pair(seq) for seq in tuples ]:
print k, u, v
It is a code to post some data to HTML server.
Even though usually the POST values are of type(name, value), if file
transfer is involved, then POST values change to (name, filename,
value).
My view was that since filename is a rare occurance and doesnt make
sense in a usual POST, I had not kept it as a full 3 tuple.
Since so many programmers (that too much more capable than me) are
suggesting that it is code smell, I am reviewing my decision.
Strange that nobody has suggested:
for Tup in Lst:
for item in Tup:
print item,
print
Because if I recall correctly, all the OP was doing was printing the stuff.
Gets a bit hairier if you want to return the values though. - if you
replace the first print statement above with a yield and delete the
second, bare print, you lose knowledge of which tuple the item
belongs to.
It is not trivial to do if you don't have a priori knowledge of
the maximum and minimum tuple length.
Seems to me it is one of those gems that is a PITA to do completely
generally - basically because you don't know when you call it how
many items to unpack - so you have to return a count or something,
or just fall back on a two step approach - get the tuple from the list,
then do something with the items in the tuple.
- Hendrik
>> tuples = [(1, 2), (3, 4, 5), (6, 7)]
>
> It is a code to post some data to HTML server.
> Even though usually the POST values are of type(name, value), if file
> transfer is involved, then POST values change to (name, filename,
> value).
> My view was that since filename is a rare occurance and doesnt make
> sense in a usual POST, I had not kept it as a full 3 tuple.
> Since so many programmers (that too much more capable than me) are
> suggesting that it is code smell, I am reviewing my decision.
What about using another data structure instead - like this:
class entry:
filename = None
def __init__(self, name, value, filename=None):
self.name = name
self.value = value
if filename is not None:
self.filename = filename
[entry('name', 'Gabriel'), entry('age', 18), entry('pic', picture_data,
'path/to/file')]
--
Gabriel Genellina
class entry:
filename = None
def __init__(self, name, value, filename=None):
self.name = name
self.value = value
if filename is not None:
self.filename = filename
[entry('name', 'Gabriel'), entry('age', 18), entry('pic', picture_data, 'path/to/file')]
En Sat, 03 Jan 2009 02:55:12 -0200, Kottiyath <n.kot...@gmail.com> escribió:
tuples = [(1, 2), (3, 4, 5), (6, 7)]
It is a code to post some data to HTML server.
Even though usually the POST values are of type(name, value), if file
transfer is involved, then POST values change to (name, filename,
value).
My view was that since filename is a rare occurance and doesnt make
sense in a usual POST, I had not kept it as a full 3 tuple.
Since so many programmers (that too much more capable than me) are
suggesting that it is code smell, I am reviewing my decision.
What about using another data structure instead - like this:
class entry:
filename = None
def __init__(self, name, value, filename=None):
self.name = name
self.value = value
if filename is not None:
self.filename = filename
[entry('name', 'Gabriel'), entry('age', 18), entry('pic', picture_data, 'path/to/file')]
--
Gabriel Genellina
Yet another solution:
for i in l:
k, u, v = i[0], None if len(i) == 2 else i[1], i[-1]
Is it possible to change (name, filename, value) into (name, value,
filename) instead?
In most cases optional arguments should be last. There are some very
exceptional case, where early optional argument might be better, like
python's range, which type signature is: [[start,] stop[, step]] (i.e.
with one argument, it is assigned to stop, instead of start)