Как быстро получить уникальные слова из списка? - PullRequest
0 голосов
/ 07 декабря 2018

У меня есть файл с 3 миллионами предложений (приблизительно).Каждое предложение содержит около 60 слов.Я хочу объединить все слова и найти из них уникальные слова.

Я попробовал следующий код:

 final_list = list()
 for sentence in sentence_list:
     words_list = nltk.word_tokenize(sentence)
     words = [word for word in words_list if word not in stopwords.words('english') ]
     final_list = final_list + set(words)

Этот код дает уникальные слова, но его обработка занимает слишком много времени.Около 50 тыс. Предложений в час.Для обработки может потребоваться 3 дня.

Я также пытался использовать лямбда-функции:

    final_list = list(map(lambda x: list(set([word for word in sentence])) ,sentence_list))

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

1 Ответ

0 голосов
/ 07 декабря 2018

Вы должны делать все это лениво и с как можно меньшим количеством промежуточных списков и, насколько это возможно (сокращение алкаций и времени обработки).Все уникальные слова из файла:

import itertools
def unique_words_from_file(fpath):
    with open(fpath, "r") as f:
        return set(itertools.chain.from_iterable(map(str.split, f)))

Позволяет объяснить идеи здесь.

Файловые объекты являются итеративными объектами, это означает, что вы можете перебирать строки файла!

Тогда нам нужны слова из каждой строки, которые разбивают их.В этом случае мы используем map в Python3 (или itertools.imap в Python2) для создания объекта с таким вычислением по строкам нашего файла.map и imap также ленивы, это означает, что промежуточный список не выделяется по умолчанию, и это здорово, потому что мы не будем тратить ресурсы на то, что нам не нужно!

Так как str.split возвращает список, наш map результат будет последовательностью списков строк, но нам нужно перебрать каждую из этих строк.Для этого не нужно создавать еще один list, мы можем использовать itertools.chain, чтобы сгладить этот результат!

Наконец, мы вызываем set, который будет перебирать эти слова и сохранять только одно длякаждый из них.Вуаля!

Давайте сделаем улучшение !, можем ли мы сделать str.split ленивым? Да!отметьте SO ответ :

import itertools
import re

def split_iter(string):
    return (x.group(0) for x in re.finditer(r"[A-Za-z']+", string))

def unique_words_from_file(fpath):
    with open(fpath, "r") as f:
        return set(itertools.chain.from_iterable(map(split_iter, f)))
...