Is there a better algorithm?

  • Thread starter Bruno Desthuilliers
  • Start date
B

Bruno Desthuilliers

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:... u = None
... try:
... (k, v) = i
... except ValueError:
... (k, u, v) = i
... print k, u, v

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
 
K

Kottiyath

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:.... u = None
.... try:
.... (k, v) = i
.... except ValueError:
.... (k, u, v) = i
.... print k, u, v
 
F

Fuzzyman

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

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
 
S

Steve Holden

Kottiyath said:
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:... u = None
... try:
... (k, v) = i
... except ValueError:
... (k, u, v) = i
... print k, u, v

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
 
M

Markus Brueckner

Hi,
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 ;-)
 
F

Francesco Bochicchio

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:... u = None
... try:
... (k, v) = i
... except ValueError:
... (k, u, v) = i
... 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
 
A

Andreas Waldenburger

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
 
J

J Kenneth King

Kottiyath said:
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:... u = None
... try:
... (k, v) = i
... except ValueError:
... (k, u, v) = i
... print k, u, v

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

Paul Rubin

Kottiyath said:
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.
 
B

bearophileHUGS

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
 
J

J Kenneth King

Paul Rubin said:
Kottiyath said:
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
 
G

Gerhard Häring

Kottiyath said:
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
 
N

Ned Deily

Kottiyath said:
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

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
 
A

Aaron Brady

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

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

mr

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
 
K

Kottiyath

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

Hendrik van Rooyen

bearophile said:
Fuzzyman:


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
 
G

Gabriel Genellina

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')]
 
L

Lie

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]
 
L

Lie

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)
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top