Добавление строки Python - PullRequest
       3

Добавление строки Python

2 голосов
/ 09 ноября 2011

У меня есть метод python, который берет список кортежей в форме (string, float) и возвращает список строк, которые, если их объединить, не превысят определенного предела.Я не разделяю предложения, чтобы сохранить длину вывода, но стараюсь не выходить за пределы длины предложения от требуемой длины вывода.

Например:
s: [('Where are you',1),('What about the next day',2),('When is the next event',3)]

max_length: 5
вывод: 'Where are you What about the next day'

max_length: 3
вывод: 'Where are you'

Вот что я делаю:

l=0
output = []
for s in s_tuples:
   if l <= max_length:
     output.append(s[0])
     l+=len(get_words_from(s[0]))
 return ''.join(output)

Есть ли более разумный способ убедиться, что длина выходного слова не превышает max_length, кроме остановки при достижении длины?

Ответы [ 5 ]

2 голосов
/ 09 ноября 2011

Во-первых, я не вижу причин откладывать разрыв цикла, если максимальная длина достигнута до следующей итерации.

Итак, изменяя ваш код, я придумываю следующий код:

s_tuples = [('Where are you',1),('What about the next day',2),('When is the next event',3)]


def get_words_number(s):
    return len(s.split())


def truncate(s_tuples, max_length):
    tot_len = 0
    output = []
    for s in s_tuples:
        output.append(s[0])
        tot_len += get_words_number(s[0])
        if tot_len >= max_length:
            break
    return ' '.join(output)


print truncate(s_tuples,3)

Во-вторых, мне действительно не нравится, что создается временный объект output. Мы можем передать метод join с помощью итератора, который перебирает начальный список, не дублируя информацию.

def truncate(s_tuples, max_length):

    def stop_iterator(s_tuples):
        tot_len = 0
        for s,num in s_tuples:
            yield s
            tot_len += get_words_number(s)
            if tot_len >= max_length:
                break

    return ' '.join(stop_iterator(s_tuples))


print truncate(s_tuples,3)

Кроме того, в ваших примерах вывод немного больше, чем установленный максимум слов. Если вы хотите, чтобы количество слов всегда было меньше предела (но все же максимально возможного), чем просто поставить yield после проверки на пределе:

def truncate(s_tuples, max_length):

    def stop_iterator(s_tuples):
        tot_len = 0
        for s,num in s_tuples:
            tot_len += get_words_number(s)
            if tot_len >= max_length:
                if tot_len == max_length:
                    yield s
                break
            yield s

    return ' '.join(stop_iterator(s_tuples))


print truncate(s_tuples,5)
1 голос
/ 09 ноября 2011

Один более разумный способ - выйти из цикла, как только вы превысите max_length, так что вы не будете циклически перебирать остальную часть списка без всякой причины:

for s in s_tuples:
    if l > max_length:
        break
    output.append(s[0])
    l += len(get_words_from(s[0]))
return ''.join(output)
1 голос
/ 09 ноября 2011

Ваш код не останавливается при достижении лимита. «max_length» - это плохое имя ... это НЕ «максимальная длина», ваш код позволяет превышать его (как в первом примере) - это преднамеренно? «л» - плохое имя; давайте назовем это tot_len. Вы даже продолжаете, когда tot_len == max_length. В вашем примере показано соединение с пробелом, но ваш код этого не делает.

Возможно, вам нужно что-то вроде:

tot_len = 0
output = []
for s in s_tuples:
    if tot_len >= max_length:
        break
    output.append(s[0])
    tot_len += len(get_words_from(s[0]))
return ' '.join(output)
1 голос
/ 09 ноября 2011

что должен контролировать max_length? общее количество слов в возвращенном списке? я бы ожидал, что max_length из пяти даст только 5 слов, а не 8.

EDIT: я бы держал два списка, так как я думаю, что их легко читать, но некоторым могут не понравиться дополнительные издержки:

def restrictWords(givenList, whenToStop):
    outputList = []
    wordList = []
    for pair in givenList:
        stringToCheck = pair[0]
        listOfWords = stringToCheck.split()
        for word in listOfWords:
            wordList.append(word)
        outputList.append( stringToCheck )
        if len( wordList ) >= whenToStop:
            break
    return outputList

так что для

testList = [ ('one two three',1),
             ('four five',2),
             ('six seven eight nine',3) ]

2 должен дать вам ['one two three'] 3 должен дать вам ['one two three'] 4 должен дать вам ['one two three', 'four five']

0 голосов
/ 09 ноября 2011

Если NumPy доступен, то следующее решение с использованием работ по усвоению списка.

import numpy as np

# Get the index of the last clause to append.
s_cumlen = np.cumsum([len(s[0].split()) for s in s_tuples])
append_until = np.sum(s_cumlen < max_length)

return ' '.join([s[0] for s in s_tuples[:append_until+1]])

Для ясности: s_cumlen содержит кумулятивные суммы количества слов в ваших строках.

>>> s_cumlen
array([ 3,  8, 13])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...