# Is there a better algorithm?

Discussion in 'Python' started by Bruno Desthuilliers, Jan 2, 2009.

1. ### Bruno DesthuilliersGuest

Kottiyath a écrit :
> I have the following list of tuples:
> L = [(1, 2), (3, 4, 5), (6, 7)]
>
> 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?

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

Bruno Desthuilliers, Jan 2, 2009

2. ### KottiyathGuest

I have the following list of tuples:
L = [(1, 2), (3, 4, 5), (6, 7)]

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?

Kottiyath, Jan 2, 2009

3. ### FuzzymanGuest

On Jan 2, 6:11 pm, Kottiyath <> wrote:
> I have the following list of tuples:
> L = [(1, 2), (3, 4, 5), (6, 7)]
>
> 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/

Fuzzyman, Jan 2, 2009
4. ### Steve HoldenGuest

Kottiyath wrote:
> I have the following list of tuples:
> L = [(1, 2), (3, 4, 5), (6, 7)]
>
> 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?

L = [(1, 2), (3, 4, 5), (6, 7)]
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/

Steve Holden, Jan 2, 2009
5. ### Markus BruecknerGuest

Hi,

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

Markus Brueckner, Jan 2, 2009
6. ### Francesco BochicchioGuest

Kottiyath ha scritto:
> I have the following list of tuples:
> L = [(1, 2), (3, 4, 5), (6, 7)]
>
> 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?

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

Francesco Bochicchio, Jan 2, 2009
7. ### Andreas WaldenburgerGuest

On Fri, 02 Jan 2009 19:55:43 +0100 Markus Brueckner <>
wrote:

> 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).

Andreas Waldenburger, Jan 2, 2009
8. ### J Kenneth KingGuest

Kottiyath <> writes:

> I have the following list of tuples:
> L = [(1, 2), (3, 4, 5), (6, 7)]
>
> 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?

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.

J Kenneth King, Jan 2, 2009
9. ### Paul RubinGuest

Kottiyath <> writes:
> I have the following list of tuples:
> L = [(1, 2), (3, 4, 5), (6, 7)]
> I want to loop through the list and extract the values.

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.

Paul Rubin, Jan 2, 2009
10. ### Guest

Fuzzyman:

> 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

, Jan 2, 2009
11. ### J Kenneth KingGuest

Paul Rubin <http://> writes:

> Kottiyath <> writes:
>> I have the following list of tuples:
>> L = [(1, 2), (3, 4, 5), (6, 7)]
>> I want to loop through the list and extract the values.

>
> 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.

Very true. +1

J Kenneth King, Jan 2, 2009
12. ### Gerhard HäringGuest

Kottiyath wrote:
> I have the following list of tuples:
> L = [(1, 2), (3, 4, 5), (6, 7)]
>
> I want to loop through the list and extract the values.
> The only algorithm I could think of is: [...]

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

Gerhard Häring, Jan 2, 2009
13. ### Ned DeilyGuest

In article <>,
J Kenneth King <> wrote:
> Kottiyath <> writes:
> > I have the following list of tuples:
> > L = [(1, 2), (3, 4, 5), (6, 7)]
> >
> > 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?

>
> 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.

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,

Ned Deily, Jan 2, 2009
14. ### Aaron BradyGuest

On Jan 2, 12:11 pm, Kottiyath <> wrote:
> I have the following list of tuples:
> L = [(1, 2), (3, 4, 5), (6, 7)]
>
> 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:
k, u, v= i[ 0 ], i[ 1 ], i[ -1 ]
if len( i )== 2: u= None

Aaron Brady, Jan 2, 2009
15. ### mrGuest

As has been noted, the best is to fix the input to be regular-3-
tuples. For the fun of it, here's another variation of a solution:

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

mr, Jan 2, 2009
16. ### KottiyathGuest

On Jan 3, 2:38 am, mr <> wrote:
> As has been noted, the best is to fix the input to be regular-3-
> tuples. For the fun of it, here's another variation of a solution:
>
> 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.

Kottiyath, Jan 3, 2009
17. ### Hendrik van RooyenGuest

bearophile wrote:

>Fuzzyman:
>
>> 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.

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

Hendrik van Rooyen, Jan 3, 2009
18. ### Gabriel GenellinaGuest

En Sat, 03 Jan 2009 02:55:12 -0200, Kottiyath <>
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

Gabriel Genellina, Jan 6, 2009
19. ### LieGuest

On Jan 3, 4:38 am, mr <> wrote:
> As has been noted, the best is to fix the input to be regular-3-
> tuples. For the fun of it, here's another variation of a solution:
>

<snip>

Yet another solution:

for i in l:
k, u, v = i[0], None if len(i) == 2 else i[1], i[-1]

Lie, Jan 13, 2009
20. ### LieGuest

On Jan 3, 11:55 am, Kottiyath <> wrote:
> On Jan 3, 2:38 am, mr <> wrote:
>

<snip>
> 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.

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)

Lie, Jan 13, 2009

## Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.