Простая функция mapreduce — использование python

Я пытаюсь лучше понять программирование больших данных, но почти ничего не знаю о python. Поэтому я использую парадигму mapreduce и практически в python я обрабатываю некоторые текстовые файлы, хранящиеся в каком-то каталоге, скажем, mydir, так что мой источник данных:

global_file = glob.glob("mydir/*")

def file_contents(file_name):
     f = open(file_name)
     try:
         return f.read()
     finally:
         f.close()

datasource = dict((file_name, file_contents(file_name)) for file_name in global_file)

тогда моя функция mapreduce

#each line in each text file is structured as follow : paper-id:::author1::author2::…. ::authorN:::title
def mapfn(k, v):
    for w in v.splitlines():
        separator = w.split('\:\:|\:\:\:')
        for x in separator[1:len(separator)-1]:
            for y in separator[-1].split():
                yield x + y, 1

Сначала k и v будут обозначать пару ключ-значение, где k — это идентификатор файла, а v — содержимое последнего файла. (В конце я хочу получить количество вхождений каждого слова, сгруппированного по автору)

Теперь проблема в том, что когда я запускаю алгоритм, я получаю результат пустого массива. Правилен ли мой синтаксис Python?


person epsilones    schedule 22.04.2013    source источник
comment
Ваш синтаксис правильный, если у вас нет SyntaxError. Ваши имена могли бы быть лучше, и ваше регулярное выражение не работает так, как вы ожидаете, но это другой момент. Я сильно подозреваю, что ваша проблема связана с заполнением вашего источника данных по относительному пути. Просто распечатайте свою переменную global_file, чтобы узнать, получили ли вы что-нибудь.   -  person bruno desthuilliers    schedule 22.04.2013
comment
@brunodeshuilliers Я обновил свой пост. У меня все еще есть пустой массив результатов. Когда я распечатываю источник данных, я получаю правильный контент. Обратите внимание, что я изменил свою функцию mapfn, чтобы не использовать библиотеку re. Есть ли у вас какие-либо идеи ?   -  person epsilones    schedule 22.04.2013


Ответы (1)


Я частично переписал вашу функцию mapfn с лучшими именами и правильным регулярным выражением для разделения, а также добавил простой тест:

import re

datasource = {
    "foo":(
        "paper-1:::author1::author2::authorN:::title1\n" 
        "paper-2:::author21::author22::author23::author2N:::title2\n"
        "paper-3:::author31::author32:::title3"
        )
    }

def mapfn(k, v):
    for line in v.splitlines():
        data = re.split(r":{2,3}", line)
        words = data[-1].split()
        for author in data[1:-1]:
            for word in words:
                yield author + word, 1


def main():
    for k, v in datasource.items():
        for result in mapfn(k, v):
            print result

if __name__ == "__main__":
    main()

Это дает следующие результаты:

bruno@betty ~/Work/playground $ python mapf.py 
('author1title1', 1)
('author2title1', 1)
('authorNtitle1', 1)
('author21title2', 1)
('author22title2', 1)
('author23title2', 1)
('author2Ntitle2', 1)
('author31title3', 1)
('author32title3', 1)

Не уверен, что это то, что вы ожидали, но, по крайней мере, это дает некоторый результат. У меня пока нет практического опыта работы с mapReduce, поэтому вам придется либо рассказать больше о контексте и о том, как вы запускаете свой код, либо подождать, пока местный гуру mapReduce не вмешается.

person bruno desthuilliers    schedule 24.04.2013