2017-02-20 15 views
3

Я экспериментирую с использованием map, filter и reduce в Python 3.6 на данный момент. То, что я пытаюсь сделать, дано в списке словарей, измените все значения, связанные с определенным ключом, на значение нижнего регистра. Например:Как использовать карту для строчных строк в словаре?

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. 

Я попытался использовать карту сначала.

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

Однако, это только кажется, возвращает список всех контент-сообщений в списке и не perserve в формат словаря. Я не верю, что reduce был бы правильным в этом сценарии, потому что я не хочу возвращать ни одного значения в конце, и filter, похоже, не имеет смысла ни здесь.

Как использовать map, reduce, или filter для этого решения?

+0

Нет, 'reduce()' и 'filter()' не являются подходящими инструментами здесь. Они будут делать совсем другие вещи. 'filter()' используется для * выбора элементов * из списка, а 'reduce()' используется для создания накопления. Как сумма или список или что-то еще, требующее, чтобы промежуточный результат обновлялся со следующим элементом из последовательности. Это не те инструменты, которые вы ищете. –

+0

Есть ли в словарях какие-либо ключи, которые нужно сохранить? Является ли обновление словарей * на месте приемлемым или вы должны создавать копии? –

+0

Вы хотите * изменить * значения в существующем словаре, или вы хотите вернуть * новый * словарь с нижним регистром? – BrenBarn

ответ

2

(Обратите внимание, что этот ответ предполагает, что вы используете Python 2, если вы используете Python 3 принять во внимание, что map() возвращает итератор и вам нужно добавить петлю из своего рода, чтобы увидеть результаты).

Если вы настаиваете на использовании map(), то вы хотите, чтобы создать новую функцию, чтобы применить к каждому существующему словарю:

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) 

dict_lowercase_content() не делает никаких предположений о том, что ключи присутствуют в словаре; он создаст мелкую копию всех ключей, а , если a content ключ присутствует нижний.

Конечно, если вы можете быть уверены в том, что ключ и всегда присутствует только ключ content, вы можете просто создать совершенно новые словари только с этим ключом;

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

Если обновление словарей на месте прекрасно, однако (что было бы более эффективным), просто использовать цикл:

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

Обратите внимание, что эта функция возвращает None! Это соглашение Python; при изменении изменяемых объектов на месте, не возвращайте эти объекты снова, поскольку у вызывающего уже есть ссылка.

Вы не можете использовать reduce() или filter() для этой работы.

  • filter()выбирает элементы из Iterable. Вы не выбираете, вы трансформируетесь.

  • reduce()элементы агрегатов; каждый элемент от входа передается функции вместе с текущим результатом; независимо от возвращаемой функции, принимается как обновленный результат.Подумайте о суммировании или конкатенировании или обходе дерева. Опять же, вы не агрегируете, вы трансформируетесь.

+0

Я знаю, что вы знаете :), но ... когда вы печатаете результат 'to_lowercase()', как это делает OP, вы получаете '<объект карты в 0x0000000002xxxxxxx>', если вы не используете python 2 или не конвертируете в 'list'. Вот почему я не использую карту много в конце цепочки (хорошо видя вопрос, OP явно использует python 2) –

+0

@ Jean-FrançoisFabre: факт, что они также смотрят на сокращение, является мертвой поддачей. –

+0

да, я тоже это видел. К счастью, теперь 'reduce' является« скрытым »(похороненным?) В' functools', и никто никогда не имеет идеи его использования: вы не получаете дополнительных очков за использование 'reduce'! –

2

С map:

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

Без map:

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

Без map, но более прочный:

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

Простой золь социологическое загрязнение, чтобы получить список новой dicts с нижнего регистром значения:

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

Выхода:

[{'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.'}] 
2

карты() является встроенной функцией более высокого порядка, что преобразование коллекции. Мы предоставляем анонимную функцию (лямбда) для выполнения карты вместо того, чтобы предоставлять сбор в качестве самого аргумента. Один из способов добиться того, что вы хотите, будет:

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