Turn cycle into higher order function

Asked

Viewed 121 times

0

Good afternoon, I have this function containing a cycle:

def ciclo(x,y):
    lista = []
    for i in x:
        if i[0]==y:
            lista.append(i[3])
    return sorted(lista)

And I wanted to turn it into a line of code, using the python map function.

I already got this: sorted(map(lambda i: i[3], x))

But this contains only the cycle, the if i[0]==y i don’t know how to get it inside the map function.

2 answers

3

In Python that’s a line:

sorted(i[3] for i in x if i[0] == y)

Forget the use of "map" in general it is more complicated than the "Generator Expressions" and "list comprehensions" that we have embedded in the language - these fancy names are for use of the "for" command in an expression inline, as I did above - and allow, without using the functions "map", "filter", or the keyword "lambda" the mapping and filtering of any data set:

Basically, you write it "<expressão> for item in <iterador> if <expressão-de-filtro>" anywhere where the language expects an iterator - it will give you all the items of the iterator, and for each, it will process the < Expressão> if the expressão-de-filtro is true. That is, the initial expression plays the role of "map", and the expression after "if" plays the role of "filter".

If you want the final result in a list, put that syntax in square brackets. ([<expressão> for item in <iterador> if <expressão-de-filtro>]) - in case, as you want the results ordered, instead I passed the iterator to a call to sorted that returns an object list already ordained.

The expression I gave as an answer above would be the equivalent of:

map((lambda i: i[3]), filter((lambda i: i[0] == y), x) )   

(that is, the iterator returned by the call to filter is the sequence parameter for calling the map - is much harder to read)

(also note that it is best to protect the Lambda with parentheses to avoid ambiguity, for human readers, whether the "," indicates the end of the lambda, or indicates that the lambda will return a tuple, rather than a single result)

0


You could use conditional expressions (kind of an exotic ternary) and return None case [0] is different from y and then apply a filter to remove the Nones:

def higherOrderCycle(x, y):
    return sorted(
        filter(
            lambda v: v != None, 
            map(lambda v: v[3] if v[0] == y else None, x)
        )
    )

See that in case you’re waiting None in v[3] it would be necessary to adapt that function. Also although the implementation with higher order functions is very beautiful and within the functional paradigm it is much more obscure than the one you posted, so outside of learning I see no reason to use it in place of the other.

  • yes you’re right, I thought I could put the whole code on one line, but I see that not... thank you!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.