Python Forum
Using lambdas and map() to parse substrings in a single line
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Using lambdas and map() to parse substrings in a single line
#1
I’m learning about lambdas and the map() builtin. I’ve got an elegant lambda expression I came across online which takes a list of three subs strings and replaces all instances of “444” with an empty “”. The code accomplishes this without meticulously converting the list to a string, replacing “444” and converting back into a list (which would have been my initial unpythonic first attempt/approach).

Based on the Geeks for Geeks tutorial titled, "Python | Replace substring in list of strings" I’ve modified their script slightly. Here is my modified code with map() and a lambda expression:

content = [
   "It was all very well to say Drink me, but the wise little Alice was not going to do THAT in a hurry. 444",
   "No, I'll look first,' she said, 444",
   "and see whether its marked poison or not for she had read several nice 444"]

 # printing original list  
print(f"\nThe original list :  \n {content}")

result = list(map(lambda set_st: str.replace(set_st, "444", ""), content))
    
# print result:
print(f"\n The list after substring replacement :  \n{result} \n")
Here is the expected output:

Quote:$ python exploring_lambda.py

The original list :
['It was all very well to say Drink me, but the wise little Alice was not going to do THAT in a hurry. 444', "No, I'll look first,' she said, 444", 'and see whether its marked poison or not for she had read several nice 444']

The list after substring replacement :
['It was all very well to say Drink me, but the wise little Alice was not going to do THAT in a hurry. ', "No, I'll look first,' she said, ", 'and see whether its marked poison or not for she had read several nice ']

I am not entirely sure how or why it works so well. I struggle with line 9 in my code sample. I partially understand some of what is going on, which I will now explain to the best of my ability. I need other forum members reading this thread to jump in and correct me or fill in gaps in my explanation. Here goes:

Line 9 declares a variable called result and processes the list of sub strings (contents), by replacing all the instances of ‘444’ with empty ‘’. After all instances of 444 are replaced, Python maps and converts it back to a list.

Is that correct? What might you people add to this?

What is map() doing? The official Python docs describes the map() builtin in this way:

Quote:returns an iterator that applies function to every item of iterable, yielding the results. If additional iterable arguments are passed, function must take that many arguments and is applied to the items from all iterables in parallel. With multiple iterables, the iterator stops when the shortest iterable is exhausted.

All of this reads like a foreign language to me. This entire block quote goes over my head. Would someone kindly rephrase this in the context of my code sample above?

I understand that lambda is like a single use function which is typically invoked in a single line, for the sake of elegance and simplicity. Here it is at line 9 again: result = list(map(lambda set_st: str.replace(set_st, "444", ""), content)). I see that there are two instances of the lambda name, set_st. The second instance of set_st is a reference to itself (within itself). So would this be an example of recursion?

Also: at the same line, the str method is passed into the replace() function. How does this work? Again, here is the official Python doc on the subject of str.replace() which apparently isn’t written in plain english either:

Quote: str.replace(old, new[, count])
Return a copy of the string with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced.

Would someone be able to rephrase this in the context of my original script (above)?
Reply
#2
(Aug-28-2020, 01:59 PM)Drone4four Wrote: What is map() doing? The official Python docs describes the map() builtin in this way:

Quote:returns an iterator that applies function to every item of iterable, yielding the results. If additional iterable arguments are passed, function must take that many arguments and is applied to the items from all iterables in parallel. With multiple iterables, the iterator stops when the shortest iterable is exhausted.

All of this reads like a foreign language to me. This entire block quote goes over my head. Would someone kindly rephrase this in the context of my code sample above?

map calls the function on each item creating a new list of the items. What you've written is equivalent to

result = []
for set_st in content:
  new_value = str.replace(set_st, "444", "")
  result.append(new_value)
[/quote]

Quote:I see that there are two instances of the lambda name, set_st. The second instance of set_st is a reference to itself (within itself). So would this be an example of recursion?

There's no recursion. A lambda is simply a function without a name, so set_st is the name of the parameter to that function.

The expression lambda set_st: str.replace(set_st, "444", "") could of course be written as a named function instead:

def replace_444(set_st):
  return str.replace(set_st, "444", "")
so that the call to map would be

result = list(map(replace_444, content))
Reply
#3
Thank you, @ndc85430, this helps tremendously.

Based on your feedback, here is the next iteration of my script:

def replace_n(set_st):
   return str.replace(set_st, "\n", "")
          
def tail(filename, nums):
   with open(filename, 'r') as lines:
       result = lines.readlines()[-(nums):]
       result_without_n = list(map(replace_n, result))
       return result_without_n
 
print(tail('Alice.txt', 3))
This achieves the same thing as my original script but with a regular function instead of a lambda. Here is the output:

Quote:['including how to make donations to the Project Gutenberg Literary', 'Archive Foundation, how to help produce our new eBooks, and how to', 'subscribe to our email newsletter to hear about new eBooks.']

By the way, I noticed that when the first function is inserted in between lines 6 and 7, the script still runs and processes the text file just as well.

I still have a few questions about my new script.

At line 7, the first argument inside the map() built-in must be an iterable. Iterables are usually data structures such as strings, lists, tuples, among others. But this script, replace_n() is a function. Is it really possible to iterate over a function even when the return value of the replace_n() function is not a string, list, or tuple? At line 2, the replace() method of the str built-in is called with an empty argument, set_st. How is this possible? Why does Python continue to iterate successfully over the replace_n() function when the return value includes an empty argument? I’d expect Python to cough up Type Error since replace_n() is not an iterable. To phrase my confusion in another way: set_st is initialized at line 1 but when it is referred to at line 2, there is no value being passed in. It’s just empty. Why does the set_st argument work if it is empty? When the replace_n() function is called at line 7, no argument is specified.

Exploring map(), I came across another tutorial on Geeks for Geeks which I’ve been playing with but still don’t understand how Python is able to iterate over a function (or lambda expression):

def addition(n):
   ''' Return double of n '''
   return n + n
 # We double all numbers using map()
numbers = (1, 2, 3, 4)
result = map(addition, numbers)
print(list(result))
 
# Square all numbers using map() and lambda  
numbers = (1, 2, 3, 4, 5, 6, 7, 8, 9, 20)
result = map(lambda x: x * x, numbers)
print(list(result))
Output:

Quote:[2, 4, 6, 8]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 400]
Reply
#4
note that str.replace(set_st, "\n", "") can be simplified to set_st.replace("\n", "")
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#5
I'm reading the thread on a phone and also don't have much time to go through all of your posts in great detail right now, but some things stood out:

The first argument to map is the function, not the iterable.

There is no "iterating over a function". As I mentioned, map iterates over the iterable calling the function on each of the items. That much should be obvious from the examples you showed of squaring and doubling each item in the tuples given.
As an exercise, could you write a for loop for each of those caees You'll see that those loops look very similar; the only thing that varies is the function you're calling on the items. Once you realise that, you could write your own version of map by putting that loop inside a function whose arguments are the iterable and the function to transform each item.
Reply
#6
To talk a little about Functional programming which these lay under.
So Python has functional features(map,lambda,filter,itertools stuff),but Python is not a functional programming language.

So often there can be discussion what can be most Pytoinc and most effective,there can functional approach not the most popular in Python.
To use example as in Thread as example.
def addition(n):
   ''' Return double of n '''
   return n + n

 # We double all numbers using map()
numbers = (1, 2, 3, 4)
result = map(addition, numbers)
print(list(result))

# Using list comprehension
result = [addition(i) for i in numbers]
print(result)
Output:
[2, 4, 6, 8] [2, 4, 6, 8]
# Square all numbers using map() and lambda
numbers = (1, 2, 3, 4, 5, 6, 7, 8, 9, 20)
result = map(lambda x: x * x, numbers)
print(list(result))

# Using list comprehension
result = [x * x for x in numbers]
print(result)
Output:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 400] [1, 4, 9, 16, 25, 36, 49, 64, 81, 400]
So in many cases can using list comprehension can be look at a better way to solve this in Python.
In these simple example both sole the task,so both way here are okay,but one may be preferred if look deeper at it.

If you look at this Thread so did a trow out a map example,
but as you see in next post so did @micseydel think more about it and come up with a better solution.

If want to read more about this look at:
Functional Programming HOWTO
Functional Programming in Python
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Substitue multiple substrings in one command Pavel_47 0 799 Jul-18-2022, 01:24 PM
Last Post: Pavel_47
  Presenting multiline data into single line aaronbuhu 1 1,768 Aug-05-2021, 10:57 AM
Last Post: jamesaarr
  Find string between two substrings, in a stream of data xbit 1 2,113 May-09-2021, 03:32 PM
Last Post: bowlofred
  beginner text formatting single line to column jafrost 4 3,160 Apr-28-2021, 07:03 PM
Last Post: jafrost
  Parse String between 2 Delimiters and add as single list items lastyle 5 3,280 Apr-11-2021, 11:03 PM
Last Post: lastyle
  Print characters in a single line rather than one at a time hhydration 1 1,988 Oct-10-2020, 10:00 PM
Last Post: bowlofred
  Python convert multi line into single line formatted string karthidec 2 9,271 Dec-23-2019, 12:46 PM
Last Post: karthidec
  command line input (arg parse) and data exchange Simba 7 4,242 Dec-06-2019, 11:58 PM
Last Post: Simba
  Print string in a single line RavCOder 8 4,097 Nov-08-2019, 09:45 AM
Last Post: perfringo
  Python-for loop print into single line dragan979 4 7,005 Nov-23-2018, 01:01 AM
Last Post: wavic

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020