@denislysenko
data engineer

Что должна делать функция map в mapreduce?

Суть задания, которое я делаю:
Есть файл movies.csv (на 10 000 строк), кстати, если это имеет значение то вы можете его скачать таки образом: wget https://files.grouplens.org/datasets/movielens/ml-...

файл выглядит так:

movieId,title,genres
1,Toy Story (1995),Adventure|Animation|Children|Comedy|Fantasy
2,Jumanji (1995),Adventure|Children|Fantasy
3,Grumpier Old Men (1995),Comedy|Romance
4,Waiting to Exhale (1995),Comedy|Drama|Romance
5,Father of the Bride Part II (1995),Comedy
6,Heat (1995),Action|Crime|Thriller
7,Sabrina (1995),Comedy|Romance
8,Tom and Huck (1995),Adventure|Children
9,Sudden Death (1995),Action
...

Сейчас, с помощью подхода mapreduce мне нужно, чтобы файл, который называется mapper.py, выводил в консоль ключи и значения, где ключ это жанр фильма, а значение это название фильма и его год, при этом должна быть возможность фильтровать фильмы по названию, году и жанру по аргументом командной строки, а если мы не передаем эти аргументы, то должны выводится в консоль все фильмы.

Пример:
есть такая строка:
1,Toy Story (1995),Adventure|Animation|Children|Comedy|Fantasy

как видно, у нее несколько жанров, а в консоли mapper.py должен печатать этот фильм так:

Adventure Toy Story;1995
Animation Toy Story;1995
Children Toy Story;1995
Comedy Toy Story;1995
Fantasy Toy Story;1995

ну и так далее по всем фильмам

запускаю это я таким образом: cat files/movies.csv | python3 mapper.py [здесь можно передавать аргументы для фильтрации фильмов по желанию]
мой файл mapper.py выглядит так:

import sys
import argparse
import re


def argpars():
    parser = argparse.ArgumentParser()
    parser.add_argument('-genres',
                        type=str,
                        help='filter by genre',
                        default=''
                        )
    parser.add_argument('-year_from',
                        type=int,
                        help='filter by year (FROM YEAR)',
                        default=1800
                        )
    parser.add_argument('-year_to',
                        type=int,
                        help='filter by year (TO YEAR)',
                        default=2025
                        )
    parser.add_argument('-regexp',
                        type=str,
                        help='filter on the movie name',
                        default=''
                        )
    return parser.parse_args()


def print_result(data, year_from, year_to, name, genres_argument):
    for line in data:
        for key, value in map(line, year_from, year_to, name, genres_argument):
            print(key, "\t", str(value))


def map(line, year_from, year_to, name, genres_argument):
    list_line = line.split(",")
    list_line[2] = list_line[2][:-2]
    # filter by year and regexp
    if filter_by_year(year_from, year_to, list_line[1]) and filter_by_regexp(name, list_line[1]):
        # filter by genres
        list_genres_argument = genres_argument.split('|')
        genres = list_line[2].split('|')
        for arg_genre in list_genres_argument:
            for genre in genres:
                if filter_by_genres(genre, arg_genre):
                    key = genre
                    value = '{};{}'.format(list_line[1][:-7], list_line[1][-5:-1])
                    yield key, value


def filter_by_year(year_from, year_to, string):
    pattern = r'\(\d{4}\)'
    if re.search(pattern, string):
        year = re.search(pattern, string)
        a = year.group(0)[1:-1]
        int_year = int(a)
        if year_from <= int_year <= year_to:
            return True


def filter_by_regexp(name, string):
    pattern = name
    if re.search(pattern, string):
        return True


def filter_by_genres(genre, genres_argument):
    if genres_argument == '' and genre != '(no genres listed)':
        return True
    elif genre == genres_argument and genre != '(no genres listed)':
        return True


if __name__ == "__main__":
    args = argpars()
    print_result(sys.stdin, args.year_from, args.year_to, args.regexp, args.genres)


Этот код полностью рабочий и выполняет свою задачу правильно ( он выводит в консоль ключ и значение, где ключ это жанр, а значение это строка название_фильма;год). Но с точки зрения mapreduce здесь функция map реализована не совсем верно, хотя этот файл полностью справляется со своей задачей. Как изменить это, чтобы это выглядело более правильно? Да и вообще буду рад увидеть любой комментарий по этому коду (например: как лучше назвать функцию или переменную, кстати да, реально, может поменять названия некоторых функций, чтобы был более читабельный код? )
Но функция map должна быть, и как ее реализовать правильным образом, чтобы это полностью соответствовало подходу mapreduce? Может вообще нужно поменять структуру кода?
Что должна делать функция map в рамках моей задачи
ЧТО ДОЛЖНА ДЕЛАТЬ ФУНКЦИЯ map() в рамках моей задачи, что она должна принимать на вход, что должна возвращать?
  • Вопрос задан
  • 153 просмотра
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы