简体   繁体   中英

How to use map to lowercase strings in a dictionary?

I'm experimenting around with the use of map , filter , and reduce in Python 3.6 at the moment. What I'm trying to do is, given a list of dictionaries , change all the values associated with a certain key to a lower-case value. For example:

message_one = {"content": "I'm glad I know sign language, it's pretty handy."}
message_two = {"content": "I am on a seafood diet. Every time I see food, I eat it."}
message_three = {"content": "Labyrinths are amazing."}
messages = [message_one , message_two , message_three]

print(to_lowercase(tweets))
#to_lowercase should just return the a list of dictionaries, but content lower-cased.

I attempted to use map at first.

def to_lowercase(messages):
    lower_case = map(lambda x: x["content"].lower(), messages)
    return lower_case

However, this just seems to return a list of all the content-messages in a list and does not perserve the dictionary format. I don't believe reduce would be proper in this scenario because I'm not looking to return a single value at the end, and filter does not seem to make sense either here.

How would I use either map , reduce , or filter to achieve this job?

Simple solution to get a list of new dicts with lowercased values:

dicts = [{k:v.lower() for k,v in d.items()} for d in messages]
print(dicts)

The output:

[{'content': "i'm glad i know sign language, it's pretty handy."}, {'content': 'i am on a seafood diet. every time i see food, i eat it.'}, {'content': 'labyrinths are amazing.'}]

(Note, this answer assumes you are using Python 2; if you are using Python 3 take into account that map() returns an iterator and you'd need to add a loop of some sort to see the results).

If you insist on using map() , then you want to create a new function to apply to each existing dictionary:

def dict_lowercase_content(d):
    """Produces a copy of `d` with the `content` key lowercased"""
    copy = dict(d)
    if 'content' in copy:
        copy['content'] = copy['content'].lower()
    return copy

def to_lowercase(tweets):
    return map(dict_lowercase_content, tweets)

The dict_lowercase_content() makes no assumptions about what keys are present in the dictionary; it'll create a shallow copy of all the keys, and if a content key is present it is lowercased.

Of course, if you can be certain that only the content key is important and always present, you could just create entirely new dictionaries with just that key;

def to_lowercase(tweets):
    return map(lambda d: {'content': d['content'].lower()}, tweets)

If updating dictionaries in-place is fine however (which would be more efficient), just use a loop:

def to_lowercase(tweets):
    for tweet in tweets:
        if 'content' in tweet:
            tweet['content'] = tweet['content'].lower()

Note that this function returns None ! This is the Python convention; when altering mutable objects in-place, don't return those objects again as the caller already has a reference.

You can't use reduce() or filter() for this job.

  • filter() selects elements from the iterable . You are not selecting, you are transforming.

  • reduce() aggregates elements ; each element from the input is passed to a function together with a running result; whatever the function returns is taken as the updated result. Think summing, or concatenating, or traversing a tree. Again, you are not aggregating, you are transforming.

With map :

map(lambda x: {'content': x['content'].lower()}, messages)

Without map :

[{'content': x['content'].lower()} for x in messages]

Without map , but more robust:

[{y: x[y].lower()} for x in messages for y in x]

map() is a built-in higher order function that transform a collection. We are supplying an anonymous function(lambda) for map to execute instead of providing the collection as an argument itself. One way to achieve what you want would be:

transformed_messages = list(map(lambda x: {'content':x['content'].lower()}, messages))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM