Преобразование вложенных циклов for в понимание сглаженного списка, когда внешняя переменная используется во внутренней области

#python

#python

Вопрос:

У меня есть пара вложенных циклов, где операции внутри внутреннего цикла зависят от обоих элементов цикла.

 def ngram(inp='', mn=2, mx=60):
    """
    EG inp='the' => ['th', 'the', 'he']
    """
    out = []
    for i in range(0, len(inp)   1 - mn):
        for j in range(i   mn, min(i   mx   1, len(inp)   1)):
            out.append(inp[i:j])
    return out
  

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

То, к чему я пришел, было из этого:

 [[i, [j for j in range(i   mn, min(i   mx   1, len(inp)   1))]]
    for i in range(0, len(inp)   1 - mn)]
  

Что при inp='the' mn=2 и mx=60 приводит: [[0, [2, 3]], [1, [3]]]

Который содержит правильную информацию для создания [inp[0:2], inp[0:3], inp[1:3]]

Приводит меня к:

 [[inp[i:j] for j in range(i   mn, min(i   mx   1, len(inp)   1))]
    for i in range(0, len(inp)   1 - mn)]
  

Что: [['th', 'the'], ['he']]

Но должно быть возможно сгладить это в приведенном выше заявлении без необходимости окружать его:

 [g for lst in […above…] for g in lst]
  

Можно ли как-то сгладить ее на предыдущем шаге?

Ответ №1:

Вы можете сделать это:

 def ngram(inp='', mn=2, mx=60):
    return [inp[i:j] 
            for i in range(0, len(inp)   1 - mn)
            for j in range(i   mn, min(i   mx   1, len(inp)   1))]
  

В общем, всякий раз, когда у вас есть цикл for такой формы:

 result = []
for sub_1 in collection:
    for sub_2 in sub_1:
        …
            for sub_n in sub_(n - 1):
                result.append(element)
  

Вы можете создать эквивалентное list понимание следующего вида:

 [element for sub_1 in collection for sub_2 in sub_1 … for sub_n in sub_(n - 1)]
  

Ответ №2:

Что не так с:

 def ngram(inp='', mn=2, mx=60): 
    return [
        inp[i:j]
        for i in range(0, len(inp)   1 - mn)
        for j in range(i mn, min(i   mx   1, len(inp)   1))
    ]
  

Комментарии:

1. Ничего, это то, что я хотел сделать, но, похоже, не получилось правильно.

2. А, понятно. Вложенные циклы очень естественно преобразуются в понимание списка в некоторых случаях, здесь это довольно просто.

3.У меня почти получилось, просто перевернуто: [inp[i:j] for j in range(i mn, min(i mx 1, len(inp) 1)) for i in range(0,len(inp) 1-mn)] Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'i' is not defined

4. честно говоря, моим естественным инстинктом было бы изменить и это