# -*- mode: python; python-indent-offset: 2 -*-
from functools import reduce

## I'm puzzle with this result of reduce.  Can you spot where my mind
## is going wrong?  
##
## The problem I want to solve with /reduce/ (merely for the sake of
## exercise) is to collapse a list of lists to a list of booleans.
## The lists given as input can contain strings or integers.  The
## output value for each list will be True if the input list contains
## an integer; False otherwise.  For example, the desired
## transformation is
##   
##   [["a","b"], ["a", 1]] --> [False, True]
##
## because only the second list has an integer.  The exercise is to
## use only map, filter and reduce.  The problem can be solved by
## mapping a function that reduces each list to the desired boolean.

## Here's the scheme of a solution:

def solution(ls):
  return list(map(transform, ls))

## To transform each list, we can apply reduce with a suitable binary
## operator here called /op/

def transform(ls):
  return reduce(op, ls, False)

## The question is how to write such an operator.  I wrote this one:

def op(x, b):
  return isinstance(x, int) or b

## My hand computation produces the correct answer, but when I invoke
## functools.reduce, I get [True, True, ...] no matter what.  For
## example:

## >>> solution([[""],["aa",1]])
## [True, True]

## which is not correct.  When I write my own reduce function, I get
## the expected results.  Here's two implementations of my
## understanding of reduce:

def reduc1(op, ls, init):
  if ls == []:
    return init
  return op(ls[0], reduc1(op, ls[1:], init))

def reduc2(op, ls, init):
  r = init
  for x in ls:
    r = op(x, r)
  return r

## They both compute the expected result:
##
## >>> list(map(lambda ls: reduc1(op, ls, False), [[""], ["aa",1]]))
## [False, True]
##
## >>> list(map(lambda ls: reduc2(op, ls, False), [[""], ["aa",1]]))
## [False, True]
##
## Can you help?  Thanks so much.
-- 
https://mail.python.org/mailman3//lists/python-list.python.org

Reply via email to