problem with interface of operator.itemgetter

Simon Forman sajmikins at gmail.com
Sun Aug 16 20:33:30 CEST 2009


On Thu, Aug 13, 2009 at 11:16 PM, dou dou<nirvana117 at gmail.com> wrote:
> I have a function to do some thing like LEFT JOIN in SQL, the function use
> the itemgetter to get the "ON" and "SELECT" parameters of the two table(list
> of list), the problem is that itemgetter may return a value or a tuple of
> values, because of the inconsistent return type of itemgetter, I have to do
> 2^3 IF check,
> the function like this:
>
> def left_join(table1, on_index1, table2, on_index2, getter1, getter2):
>     """do thing like:
>     SELECT on1(table1), g1(table1), g2(table2) FROM table1
>     LEFT JOIN table2
>     ON on1(table1) == on2(table2)
>     """
>     on1 = itemgetter(*on_index1)
>     on2 = itemgetter(*on_index2)
>     g1 = itemgetter(*getter1)
>     g2 = itemgetter(*getter2)
>
>     d2 = {}
>     d2 = dict((on2(r2), r2) for r2 in table2)
>
>     #if itemgetter always return tuple, below could simple as one line
>     #return [ list(on1(r1) + g1(r1) + g2(d2.get(on1(r1)))) for r1 in table1
> ]
>
>     len_on = len(on_index1)
>     len_g1 = len(getter1)
>     len_g2 = len(getter2)
>
>     if len_on == 1:
>         if len_g1 == 1 and len_g2 == 1:
>             return [ [on1(r1), g1(r1), g2(d2.get(on1(r1)))] for r1 in table1
> ]
>         elif len_g1 == 1 and len_g2 > 1:
>             return [ list((on1(r1),g1(r1))+g2(d2.get(on1(r1)))) for r1 in
> table1 ]
>         elif len_g1 > 1 and len_g2 == 1:
>             return [ list((on1(r1),)+g1(r1)+(g2(d2.get(on1(r1))),))  for r1
> in table1 ]
>         else: #len_g1 > 1 and len_g2 > 1:
>             return [ list((on1(r1),)+g1(r1)+g2(d2.get(on1(r1)))) for r1 in
> table1 ]
>     else: # len_on > 1
>         if len_g1 == 1 and len_g2 == 1:
>             return [ list(on1(r1))+[g1(r1),g2(d2.get(on1(r1)))] for r1 in
> table1 ]
>         elif len_g1 == 1 and len_g2 > 1:
>             return [ list(on1(r1)+(g1(r1),)+g2(d2.get(on1(r1)))) for r1 in
> table1 ]
>         elif len_g1 > 1 and len_g2 == 1:
>             return [ list(on1(r1)+g1(r1)+(g2(d2.get(on1(r1))),))  for r1 in
> table1 ]
>         else: #len_g1 > 1 and len_g2 > 1:
>             return [ list(on1(r1)+g1(r1)+g2(d2.get(on1(r1)))) for r1 in
> table1 ]
>
> so is there a way to force itemgetter to return tuple even when
> itemgetter(only_have_one_argument)? or some other function to do this?
>
> Thanks.
>


You can use a little helper function to create your itemgetter like this:

def makeItemGetter(indexes):
   I = itemgetter(*indexes)
   if len(indexes) > 1:
       return I
   return lambda thing: (I(thing),)

If indexes contains only one index the itemgetter is wrapped in a
lambda that turns its output into a tuple.

HTH,
~Simon



More information about the Python-list mailing list