Mario
Mario

Reputation: 1966

How to replace your Pythonic For Loops with Map and Filter?

In the spirit of DRY, I was trying to replace and reduce a simple for-loop including if clause unsuccessfully after I read this article by Jonathan Hsu for a The Decent game. The For loop is as follows:

import sys
import math

# Auto-generated code below aims at helping you parse
# the standard input according to the problem statement.


# game loop
while 1:
    max = 0
    imax = 0
    for i in range(8):
        mountain_h = int(input()) # represents the height of one mountain, from 9 to 0. Mountain heights are provided from left to right.
        if mountain_h > max:
            max = mountain_h
            imax = i

    print(imax)

Based on Jonathan Hsu article I tried to replace for loop by map() and if-clause by filter()as follows:

from functools import reduce

# game loop
while 1:
    m = [0,1,2,3,4,5,6,7]
    max = 0
    imax = 0
    
    u = map(lambda n: mountain_h = int(input()) and print(imax), m)
    r = filter(lambda n: mountain_h > max, n)
    s = map(lambda n: max = mountain_h and imax = i, r)
  # s = reduce(lambda acc, m: acc + n, r)

Any inputs to shed light on the realization of this replacement will be appreciated.

Upvotes: 1

Views: 295

Answers (2)

chepner
chepner

Reputation: 531275

The part you aren't capturing is that your loop is implicitly producing a sequence of calls to input; that's a job for the two-argument form of iter, which will call input until it returns a given value. iter(input, None) can return an infinite number of values, since input() will never return None, but you can short-circuit that using itertools.islice to limit it to 8 calls.

Once you have the inputs (or rather, an iterator that will produce your inputs), you can use enumerate to tag each input with its sequence number and use max (with an appropriate key function) to find the largest value and its index.

from itertools import islice

while 1: 
    my_inputs = map(int, islice(iter(input, None), 8))
    imax, m = max(enumerate(my_inputs), key=lambda x: x[1])
    
    print(imax)

Piece by piece:

  1. iter(input, None) is an infinite stream of calls to input().
  2. islice(..., 8) only yields the first 8 of them.
  3. map(int, ...) calls int on each value. (Warning: this won't catch a ValueError raised by a non-integer input. There's no functional way to deal with the exception.)
  4. enumerate(my_inputs) turns a stream like 3, 7, 2 into (0, 3), (1, 7), (2, 2).
  5. max(..., key=lambda x: x[1]) on the above sequence returns (1, 7), because 7 is the largest second element of all the tuples.

You might also find the use of operator.itemgetter(1) cleaner than an explicit lambda expression as the key argument to max.


A more Pythonic version of the same approach would use a generator function to produce the stream of integer values for max/enumerate to iterate over. It also makes it easier to handle input errors. For example:

def eight_integers():
    for _ in range(8):
        while True:
            try:
                x = int(input())
            except ValueError:
                continue
            yield x

imax, m = max(enumerate(eight_integers()), key=lambda x: x[1])

Of course, you could also have eight_integers yield an index and an integer itself, eliminating the need to use enumerate.

Upvotes: 1

OneCricketeer
OneCricketeer

Reputation: 191738

So, map is to update elements within a list, filter is to remove elements, and reduce is to collect/aggregate... You are never filtering or mapping data, only gathering input, then compaing against a running max, which would be a use-case for reduce, but still unncessary given Python's max() function.

If you want Pythonic code for this, then it seems you really want a list comprehension, followed by a method that gets the max value & index within that list

values = [int(input()) for i in range(8)]
_max = max(values)
imax = len(values) - 1 - values[::-1].index(_max)  # assuming you want the last index

But note that this is effectively replacing one loop with 3 and has nothing to do with DRY principles

Upvotes: 0

Related Questions