python: токенизировать список кортежей без цикла for - PullRequest
0 голосов
/ 25 февраля 2019

У меня есть список из 2 миллионов кортежей, где первый элемент - текст, а второй - целое число.например,

list_of_tuples = [('here is some text', 1), ('this is more text', 5), ('a final tuple', 12)]

Я хотел бы маркировать первый элемент в каждом кортеже и присоединить все списки слов к сплющенному списку так, чтобы желаемый результат был.

list_of_tokenized_tuples = [(['here', 'is', 'some', 'text'], 1), (['this', 'is', 'more', 'text'], 5), (['a', 'final', 'tuple'], 12)]
list_of_all_words = ['here', 'is', 'some', 'text', 'this', 'is', 'more', 'text', 'a', 'final', 'tuple']

Такпока, я считаю, что я нашел способ добиться этого с помощью цикла for, однако из-за длины списка это действительно требует много времени.Есть ли способ, которым я могу токенизировать первый элемент в кортежах и / или сгладить список всех слов так, чтобы не было циклов?

list_of_tokenized_tuples = []
list_of_all_words = []

for text, num in list_of_tuples:
    tokenized_text = list(word_tokenize(text))
    tokenized_tuples = (tokenized_text, num)
    list_of_all_words.append(tokenized_text)
    list_of_tokenized_tuples.append(tokenized_tuples)

list_of_all_words = [val for sublist in list_of_all_words for val in sublist]

Ответы [ 3 ]

0 голосов
/ 25 февраля 2019

Используя itertools вы могли бы написать это как:

from itertools import chain, imap

chain.from_iterable(imap(lambda (text,_): word_tokenize(text), list_of_tuples))

Тестирование этого:

from itertools import chain, imap

def word_tokenize(text):
    return text.split() # insert your tokenizer here

ts = [('here is some text', 1), ('this is more text', 5), ('a final tuple', 12)]

print list( chain.from_iterable(imap(lambda (t,_): word_tokenize(t), ts)) )

Вывод

['here', 'is', 'some', 'text', 'this', 'is', 'more', 'text', 'a', 'final', 'tuple']

Я не уверен, чтоэто покупает вас, хотя, как есть для цикла в реализации функций itertools.

0 голосов
/ 26 февраля 2019

TL; DR

>>> from itertools import chain

>>> list_of_tuples = [('here is some text', 1), ('this is more text', 5), ('a final tuple', 12)]

# Split up your list(str) from the int
>>> texts, nums = zip(*list_of_tuples)

# Go into each string and split by whitespaces,
# Then flatten the list of list of str to list of str
>>> list_of_all_words = list(chain(*map(str.split, texts)))

>>> list_of_all_words
['here', 'is', 'some', 'text', 'this', 'is', 'more', 'text', 'a', 'final', 'tuple']

Если вам нужно использовать word_tokenize, то:

list_of_all_words = list(chain(*map(word_tokenize, texts)))
0 голосов
/ 25 февраля 2019

Я написал этот генератор для вас.Если вы хотите создать список, вы ничего не можете сделать (кроме понимания списка).Имея это в виду, см. Ниже, он дает вам желаемый результат, но объединен в кортеж в виде двух отдельных списков.Я сомневаюсь, что это имеет большое значение, и я уверен, что вы всегда можете немного изменить его в соответствии со своими потребностями или предпочтениями.

import timeit, random


list_of_tuples = [('here is some text', 1), ('this is more text', 5), ('a final tuple', 12)]
big_list = [random.choice(list_of_tuples) for x in range(1000)]


def gen(lot=big_list, m='tokenize'):
    list_all_words = []
    tokenised_words = []
    i1 = 0
    i2 = 0
    i3 = 0
    lol1 = len(lot)
    while i1 < lol1:
        # yield lot[i1]
        lol2 = len(lot[i1])
        while i2 < lol2:
            if type(lot[i1][i2]) == str:
                list_all_words.append((lot[i1][i2].split(), i1 + 1))
            i2 += 1
        i1 += 1
        i2 = 0
    # print(list_all_words)
    lol3 = len(list_all_words)
    while i3 < lol3:
        tokenised_words += list_all_words[i3][0]
        i3 += 1
    if m == 'list':
        yield list_all_words
    if m == 'tokenize':
        yield tokenised_words


for x in gen():
    print(x)


print(timeit.timeit(gen))
# Output of timeit: 0.2610903770813007
# This should be unnoticable on system resources I would have thought.
...