Карта уменьшает проблему в питоне - PullRequest
3 голосов
/ 27 сентября 2011

Я в настоящее время борюсь с заданием.Решение будет вводить текстовый файл и выполнять подсчет числа палиндромов и их частоты.Мне нужно использовать Map Reduce для создания

Например: строка "bab bab bab cab cac dad" выдаст:

bab 3
cab 1
dad 1

Вот то, что я имею до сих пор

def palindrome(string):
    palindromes = []
    for word in string.split(" "):
        if (word == word[::-1]):
            palindromes.append(word)
    return palindromes 

string = "abc abd bab tab cab tat yay uaefdfdu"
print map(lambda x: palindrome(x), ["bab abc dab bab bab dad crap pap pap "])

В настоящее время печатает

[['bab', 'bab', 'bab', 'dad', 'pap', 'pap', '']]

Вот моя попытка в секции уменьшения

def p(lists):
for list in lists:

set_h = set(list) 

return set_h

с помощью функции p. Я хочу создать набор всехпалиндромы найдены.Затем запустите подсчет палиндромов в списке и сделайте из этого вывод

print reduce(p, [['bab', 'bab', 'bab', 'dad', 'pap', 'pap', '']])

Я на правильном пути?

Ответы [ 5 ]

3 голосов
/ 27 сентября 2011

Я думаю, вам было бы намного легче, если бы ваши map() и reduce() входные данные были реальным списком слов. Чтобы достичь этого, .split() строка перед передачей в map(). Затем map() слово либо для себя (если ваш картограф встречает палиндром), либо None. Затем вы можете filter() результаты отбросить None значений, отсортировать их и передать reduce(). reduce() затем уменьшит его до dict, сопоставляя слова с их общим количеством.

Я не предоставлю вам рабочее решение, чтобы не отвлекаться от фактора обучения.

1 голос
/ 13 июля 2013

Было бы очень просто, если бы мы разложили проблему на маленькие задачи.В нашем случае это может быть:

  1. Отфильтровать все палиндромы из списка слов.
  2. Получить уникальные слова, чтобы найти количество.
  3. Отобразить всеуникальные слова для соответствующего количества.

Код:

words =  "bab bab bab cab cac dad"
is_palindrome = lambda word : word == word[::-1]
palindromes = filter(is_palindrome,words.split(" "))
get_count = lambda word : (word , palindromes.count(word))
unique = set(palindromes)
dict(map(get_count,unique))
Out[1]: {'bab': 3, 'cac': 1, 'dad': 1}

Вот краткое объяснение:

#Input:
    words =  "bab bab bab cab cac dad"

#Step 1: Filter out the palindromes.
    is_palindrome = lambda word : word == word[::-1]
    palindromes = filter(is_palindrome,words.split(" "))

#Step 2: Get the unique set of string to find their counts.
    unique = set(palindromes)

#Step 3: Map every unique palindrome to their respective count.
    get_count = lambda word : (word , palindromes.count(word))
    dict(map(get_count,unique))

#Output:
    Out[1]: {'bab': 3, 'cac': 1, 'dad': 1}

ПРИМЕЧАНИЕ: Карта в Python может принимать любую последовательность, а не только список, набор или диктовку.Строки в python также являются последовательностями, поэтому не удовлетворены утверждением Коди Хесса: map не может принимать строки.

Для демонстрации приведем очень простую демонстрацию:

In [10]: map(echo, "python")
Out[10]: ['p', 'y', 't', 'h', 'o', 'n']
1 голос
/ 27 сентября 2011

Разделите вашу строку в список , прежде чем вы отобразите его. map () для списков, наборов и подсказок, не строк.

word_list = words_str.split(" ")

Избегайте использования map-filter-lower , если это не предписано вашим назначением; GVR говорит так . Правильное решение использует синтаксис списка Python . На самом деле, вы можете сделать это с довольно неприятной однострочностью:

pal_count = {
    x: word_list.count(x)  # reduce-ish
    for x in word_list     # map-ish
    if x == x[::-1]        # filter-ish
    }
for x, y in pal_count.iteritems():
    print x, y             # print the results!

Разбить его ...

  1. Поймать это в объекте словаря, чтобы напечатать его позже: pal_count = {
  2. Определите возвращаемые объекты: x: word_list.count(x) Мы используем синтаксис key: value, чтобы связать палиндром, x , с его количеством вхождений. count () походит на встроенную функцию сокращения для списков.
  3. Итерация по нашему списку с для цикла , присвоение текущего значения 'x': for x in word_list
  4. Мы хотим вернуть только палиндромы, поэтому мы добавляем оператор сравнения в filter out неправильных значений: if x == x[::-1] # cool logic, btw
  5. Ура! }

Кстати, я делаю твою домашнюю работу только потому, что никогда не делал мою.

Более медленный, менее гибкий, менее переносимый, менее потрясающий эквивалентный использует вложенные для циклов:

pal_count = dict()
for x in word_list:                     # same loop
    if x == x[::-1]                     # is this a palindrome?
        if x in pal_count:              # have we seen before?
            pal_count[x] += 1
        else:                           # this one is new!
            pal_count.setdefault(x, 1)
1 голос
/ 27 сентября 2011

Для вашей функции сокращения вы должны начать с пустого слова и обновить / заполнить счетчик.Для функций снижения требуется 2 параметра, поэтому один может быть вашим диктом, а другой - вашим палиндромом.Вы можете ввести начальное значение в Reduce следующим образом:

reduce(lambda x, y: x+y, some_list, initial_value_for_x)

Посмотрите на dict's get , как установить значения по умолчанию, что должно помочь вам значительно упростить вашу функцию снижения.

0 голосов
/ 17 марта 2017

Для карты / уменьшения, используя Counter объект довольно прост.

from collections import Counter 
words = "bab bab bab cab cac dad"
words_list = words.split(" ") 
cont = Counter()
for word in words_list:
    cont[word] += 1
print(cont)
# or if you want dict
print(dict(cont))

https://docs.python.org/3/library/collections.html

...