Newbie: Struggling again 'map'

Discussion in 'Python' started by mosscliffe, May 26, 2007.

  1. mosscliffe

    mosscliffe Guest

    I thought I had the difference between 'zip' and 'map' sorted but when
    I try to fill missing entries with something other than 'None'. I do
    not seem to be able to get it to work - any pointers appreciated.

    Richard

    lista = ['a1', 'a2']
    listb = ['b10', 'b11','b12' ,'b13']

    for x,y in zip(lista, listb): # Fine Truncates as expected
    print "ZIP:", x, "<<x y>>", y

    for x,y in map(None, lista, listb): # Also fine - extends as
    expected
    print "MAP:", x, "<<x y>>", y

    for x,y in map("N/A", lista, listb): ########## Fails - Can not call a
    'str'
    print "MAP:", x, "<<x y>>", y

    def fillwith(fillchars):
    return fillchars

    for x,y in map(fillwith("N/A"), lista, listb): ########## Fails also -
    Can not call a 'str'
    print "MAP:", x, "<<x y>>", y
     
    mosscliffe, May 26, 2007
    #1
    1. Advertising

  2. mosscliffe

    Dan Bishop Guest

    On May 26, 4:54 am, mosscliffe <> wrote:
    > I thought I had the difference between 'zip' and 'map' sorted but when
    > I try to fill missing entries with something other than 'None'. I do
    > not seem to be able to get it to work - any pointers appreciated.
    >
    > Richard
    >
    > lista = ['a1', 'a2']
    > listb = ['b10', 'b11','b12' ,'b13']
    >
    > for x,y in zip(lista, listb): # Fine Truncates as expected
    > print "ZIP:", x, "<<x y>>", y
    >
    > for x,y in map(None, lista, listb): # Also fine - extends as
    > expected
    > print "MAP:", x, "<<x y>>", y
    >
    > for x,y in map("N/A", lista, listb): ########## Fails - Can not call a
    > 'str'
    > print "MAP:", x, "<<x y>>", y
    >
    > def fillwith(fillchars):
    > return fillchars
    >
    > for x,y in map(fillwith("N/A"), lista, listb): ########## Fails also -
    > Can not call a 'str'
    > print "MAP:", x, "<<x y>>", y


    zip(lista + ['N/A'] * 2, listb)
     
    Dan Bishop, May 26, 2007
    #2
    1. Advertising

  3. In <>, mosscliffe
    wrote:

    > for x,y in map(None, lista, listb): # Also fine - extends as
    > expected
    > print "MAP:", x, "<<x y>>", y
    >
    > for x,y in map("N/A", lista, listb): ########## Fails - Can not call a
    > 'str'
    > print "MAP:", x, "<<x y>>", y
    >
    > def fillwith(fillchars):
    > return fillchars
    >
    > for x,y in map(fillwith("N/A"), lista, listb): ########## Fails also -
    > Can not call a 'str'
    > print "MAP:", x, "<<x y>>", y


    `map()` expects a function as first argument that will be applied to the
    elements in the other the arguments which have to be iterable. That you
    can give `None` as a function and the resulting behavior is IMHO a very
    ugly thing and has not much to to with the semantics expected from a
    `map()` function. The `None` is not the default fill value but a
    placeholder for the identity function.

    Ciao,
    Marc 'BlackJack' Rintsch
     
    Marc 'BlackJack' Rintsch, May 26, 2007
    #3
  4. mosscliffe schreef:
    > for x,y in map("N/A", lista, listb): ########## Fails - Can not call a
    > 'str'
    > print "MAP:", x, "<<x y>>", y
    >
    > def fillwith(fillchars):
    > return fillchars
    >
    > for x,y in map(fillwith("N/A"), lista, listb): ########## Fails also -
    > Can not call a 'str'
    > print "MAP:", x, "<<x y>>", y


    The first argument to map is a function, which is called with the items
    of the argument sequences. If the first argument is None, a default
    function is used which returns a tuple of the items. In the case that
    two input sequences are provided:

    map(None, lista, listb)

    is equivalent to:

    def maketuple(a, b):
    return a, b
    map(maketuple, lista, listb)

    So what you want to do can be done with map like this:

    def make_fill_missing(fillchars):
    def fill_missing(a, b):
    if a is None:
    a = fillchars
    if b is None:
    b = fillchars
    return a, b
    return fill_missing

    map(make_fill_missing("N/A"), lista, listb))



    --
    If I have been able to see further, it was only because I stood
    on the shoulders of giants. -- Isaac Newton

    Roel Schroeven
     
    Roel Schroeven, May 26, 2007
    #4
  5. mosscliffe

    mosscliffe Guest

    Thank you all very much.

    I particularily found Roel's explanation and example most useful.

    At this stage I am getting my head around syntax, rather than language
    theory, although I know, I have to understand that as well.

    Thanks again.

    Richard

    On 26 May, 12:47, Roel Schroeven <>
    wrote:
    > mosscliffe schreef:
    >
    > > for x,y in map("N/A", lista, listb): ########## Fails - Can not call a
    > > 'str'
    > > print "MAP:", x, "<<x y>>", y

    >
    > > def fillwith(fillchars):
    > > return fillchars

    >
    > > for x,y in map(fillwith("N/A"), lista, listb): ########## Fails also -
    > > Can not call a 'str'
    > > print "MAP:", x, "<<x y>>", y

    >
    > The first argument to map is a function, which is called with the items
    > of the argument sequences. If the first argument is None, a default
    > function is used which returns a tuple of the items. In the case that
    > two input sequences are provided:
    >
    > map(None, lista, listb)
    >
    > is equivalent to:
    >
    > def maketuple(a, b):
    > return a, b
    > map(maketuple, lista, listb)
    >
    > So what you want to do can be done with map like this:
    >
    > def make_fill_missing(fillchars):
    > def fill_missing(a, b):
    > if a is None:
    > a = fillchars
    > if b is None:
    > b = fillchars
    > return a, b
    > return fill_missing
    >
    > map(make_fill_missing("N/A"), lista, listb))
    >
    > --
    > If I have been able to see further, it was only because I stood
    > on the shoulders of giants. -- Isaac Newton
    >
    > Roel Schroeven
     
    mosscliffe, May 26, 2007
    #5
  6. On May 26, 7:47 am, Roel Schroeven <>
    wrote:
    > mosscliffe schreef:
    >
    > > for x,y in map("N/A", lista, listb): ########## Fails - Can not call a
    > > 'str'
    > > print "MAP:", x, "<<x y>>", y

    >
    > > def fillwith(fillchars):
    > > return fillchars

    >
    > > for x,y in map(fillwith("N/A"), lista, listb): ########## Fails also -
    > > Can not call a 'str'
    > > print "MAP:", x, "<<x y>>", y

    >
    > The first argument to map is a function, which is called with the items
    > of the argument sequences. If the first argument is None, a default
    > function is used which returns a tuple of the items. In the case that
    > two input sequences are provided:
    >
    > map(None, lista, listb)
    >
    > is equivalent to:
    >
    > def maketuple(a, b):
    > return a, b
    > map(maketuple, lista, listb)
    >
    > So what you want to do can be done with map like this:
    >
    > def make_fill_missing(fillchars):
    > def fill_missing(a, b):
    > if a is None:
    > a = fillchars
    > if b is None:
    > b = fillchars
    > return a, b
    > return fill_missing
    >
    > map(make_fill_missing("N/A"), lista, listb))


    And here's a generalized iterator-based version:

    def ifill(default, *iterables):
    from itertools import repeat
    nextfuncs = [iter(iterable).next for iterable in iterables]
    # how many non-exhausted iterators are left
    num_left = [len(iterables)]
    # closure for iterating over the next value of each iterator
    def iter_next_tuple_values():
    for i,next in enumerate(nextfuncs):
    try: yield next()
    except StopIteration:
    num_left[0] -= 1
    nextfuncs = next = repeat(default).next
    yield next()
    while True:
    t = tuple(iter_next_tuple_values())
    if not num_left[0]:
    break
    yield t

    # example
    lista = ['a1', 'a2']
    listb = ['b10', 'b11', 'b12', 'b13']

    for iterables in [
    (lista, listb),
    (lista, listb, ()),
    ((), listb, ()),
    ((), (), ())
    ]:
    print list(ifill(None, *iterables)) == map(None, *iterables)


    George
     
    George Sakkis, May 26, 2007
    #6
  7. mosscliffe

    7stud Guest

    1) If you write (...) after a function name, it executes the
    function(except when defining a function). And when you write (...)
    after a function name it's known as a "function call":

    def calc():
    return 3.5

    result = calc() + 2


    2) Function calls are replaced in the code by the function's return
    value:

    result = calc() + 2

    becomes:

    result = 3.5 + 2



    3) map() and zip() perform two different tasks. zip() takes two(or
    more) sequences, and it returns a list of tuples, where each tuple
    consists of one element from each of the sequences:

    s1 = [1, 2, 3]
    s2 = [10, 20, 30, 40]

    print zip(s1, s2)
    --->[(1, 10), (2, 20), (3, 30)]

    If one sequence is shorter than the other, zip() stops when it reaches
    the end of the shorter sequence.

    On the other hand, map() applies a given function to each member of a
    sequence and returns a list that contains the return values of the
    function:

    s1 = [1, 2, 3]

    def f(x):
    return x*2

    result = map(f, s1)
    print result
    ---->[2, 4, 6]

    If you call map() with a function and two sequences, e.g.:

    map(f, s1, s2)

    then the specified function will be called with two arguments--using
    one element from each sequence for the arguments:

    s1 = [1, 2, 3]
    s2 = [10, 20, 30]

    def f(x,y):
    return x + y

    result = map(f, s1, s2)
    print result
    ----->[11, 22, 33]

    If one sequence is shorter than the other, then unlike zip() which
    stops at the end of the shorter sequence, map() continues on until it
    reaches the end of the longer sequence. In that case, since the
    shorter sequence won't have any more values to provide, map() uses
    None. In other words, map() calls the specified function with one
    argument from the longer sequence and the other argument being None:

    s1 = [1, 2, 3]
    s2 = [10, 20, 30, 40, 50]

    def f(x,y):
    return x + y

    result = map(f, s1, s2)
    print result
    Traceback (most recent call last):
    File "2pythontest.py", line 7, in ?
    result = map(f, s1, s2)
    File "2pythontest.py", line 5, in f
    return x + y
    TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'

    The error results from the attempt inside the function f to add the
    value 40 from the second sequence to None(which is used in lieu of a
    value from the first sequence). So if you want to use map() with
    sequences of different lengths, before you perform any calculations in
    the specified function, you have to first check to see if one of the
    values is None. If one of the values is None, then you have to take
    some special action:

    s1 = [1, 2, 3]
    s2 = [10, 20, 30, 40, 50]

    def f(x,y):
    if x==None or y==None:
    return "N/A"
    return x + y

    result = map(f, s1, s2)
    print result
    ---->[11, 22, 33, 'N/A', 'N/A']


    > for x,y in map(None, lista, listb): # Also fine - extends as
    > expected
    > print "MAP:", x, "<<x y>>", y


    That is not expected at all--at least not by me. You have to decipher
    the fine print of the map() description to expect that result. My
    expectation is the code will fail since None is not a function, and
    the first argument to map() is supposed to be a function. In any
    case, that should be considered aberrant behavior--not the normal way
    map() works.

    > for x,y in map("N/A", lista, listb): ########## Fails - Can not call a
    > 'str'
    > print "MAP:", x, "<<x y>>", y


    That is as expected since "N/A" is not a function. After all, how can
    you call a string?

    s = "hello world"
    print s(10)

    Obviously, that's nonsensical.

    > def fillwith(fillchars):
    > return fillchars
    >
    > for x,y in map(fillwith("N/A"), lista, listb): ########## Fails also -
    > Can not call a 'str'


    In the last line of code, the function call is replaced in the code by
    the function's return value(see point 2 above--at the very top of the
    post). Since the return value of the function call fillwith("N/A") is
    "N/A", the last line of your code becomes:

    for x,y in map("N/A", lista, listb)

    and once again map() is unable to call a string:

    s = "N/A"
    print s(lista[0], listb[0])

    In conclusion,

    zip() returns a list of tuples (where each tuple contains one element
    from each sequence).

    map() returns a list (where each element of the list is the return
    value of a function).
     
    7stud, May 27, 2007
    #7
    1. Advertising

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.
Similar Threads
  1. Bob Dubery

    Java Newbie struggling with threads

    Bob Dubery, Jun 9, 2004, in forum: Java
    Replies:
    10
    Views:
    574
    John C. Bollinger
    Jun 11, 2004
  2. Replies:
    8
    Views:
    408
    Old Wolf
    May 17, 2005
  3. jpmad4it
    Replies:
    1
    Views:
    299
    jpmad4it
    Aug 15, 2008
  4. François de Dardel

    Newbie struggling with form validation (1st question)

    François de Dardel, Aug 4, 2004, in forum: Javascript
    Replies:
    1
    Views:
    79
    Java script Dude
    Aug 4, 2004
  5. Jean Dubois

    [newbie] struggling wth tkinter

    Jean Dubois, Dec 7, 2013, in forum: Python
    Replies:
    11
    Views:
    282
    Jean Dubois
    Dec 8, 2013
Loading...

Share This Page