Подтвердить что ты не робот

Рекурсивное понимание списка в Python?

Можно ли определить рекурсивное понимание списка в Python?

Возможно, упрощенный пример, но что-то вроде:

nums = [1, 1, 2, 2, 3, 3, 4, 4]
willThisWork = [x for x in nums if x not in self] # self being the current comprehension

Возможно ли подобное?

4b9b3361

Ответ 1

Нет, нет (документированный, прочный, стабильный,...;-) способ ссылаться на "текущее понимание". Вы можете просто использовать цикл:

res = []
for x in nums:
  if x not in res:
    res.append(x)

конечно, это очень дорого (O (квадрат N)), поэтому вы можете оптимизировать его с помощью вспомогательного set (я предполагаю, что сохранение порядка элементов в res конгруэнтно по отношению к элементам в nums, в противном случае set(nums) сделает вас; -)...:

res = []
aux = set()
for x in nums:
  if x not in aux:
    res.append(x)
    aux.add(x)

это очень быстро для очень длинных списков (O (N) вместо квадратов N).

Изменить: в Python 2.5 или 2.6, vars()['_[1]'] может действительно работать в той роли, которую вы хотите для self (для не-вложенного listcomp)... вот почему я определил свой, прояснив там документированный, надежный, стабильный способ доступа к "составленному списку" - это своеобразное недокументированное "имя" '_[1]' (намеренно выбранное не является допустимым идентификатором; ) является вершиной "артефактов реализации", и любой используемый на ней код заслуживает того, чтобы его портили, -).

Ответ 2

Собственно вы можете! Этот пример с объяснением, надеюсь, проиллюстрирует, как это сделать.

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

print [ (lambda f,v: v >= 5 and v or f(f,v+1))(lambda g,i: i >= 5 and i or g(g,i+1),i) for i in [1,2,3,4,5,6] ]

результат:

[5, 5, 5, 5, 5, 6]
>>> 

по существу две анонимные функции взаимодействуют таким образом:

let f(g,x) = {  
                 expression, terminal condition
                 g(g,x), non-terminal condition
             }

let g(f,x) = {  
                 expression, terminal condition
                 f(f,x), non-terminal condition
             }

сделать g, f "той же" функцией, за исключением того, что в одном или обоих добавьте предложение, в котором параметр изменен, чтобы вызвать условие терминала, и затем перейти f (g, x) таким образом, g становится копией f, которая делает это следующим образом:

f(g,x) = {  
                 expression, terminal condition
                 {
                    expression, terminal condition,
                    g(g,x), non-terminal codition
                 }, non-terminal condition
             }

Вам нужно сделать это, потому что вы не можете получить доступ к анонимной функции при ее выполнении.

i.e

(lambda f,v: somehow call the function again inside itself )(_,_)

поэтому в этом примере пусть A = первая функция, а B - вторая. Мы называем A проходящим B как f и я как v. Теперь, когда B является по существу копией A, и это переданный параметр, вы можете теперь называть B, который похож на вызов A.

Это генерирует факториалы в списке

print [ (lambda f,v: v == 0 and 1 or v*f(f,v-1))(lambda g,i: i == 0 and 1 or i*g(g,i-1),i) for i in [1,2,3,5,6,7] ]

[1, 2, 6, 120, 720, 5040]
>>> 

Ответ 3

нет. он не будет работать, не существует self для ссылки, пока выполняется выполнение списка.

И главная причина, конечно, в том, что списки, которые не предназначены для этого использования.

Ответ 4

Не уверен, что это то, что вы хотите, но вы можете писать вложенные списки:

xs = [[i for i in range(1,10) if i % j == 0] for j in range(2,5)]
assert xs == [[2, 4, 6, 8], [3, 6, 9], [4, 8]]

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

xs = sorted(set([1, 1, 2, 2, 3, 3, 4, 4]))
assert xs == [1, 2, 3, 4]

Ответ 5

Нет.

Но похоже, что вы пытаетесь составить список уникальных элементов в nums.

Вы можете использовать set:

unique_items = set(nums)

Обратите внимание, что элементы в числах должны быть хешируемыми.

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

unique_items = []
for i in nums:
    if i not in unique_items:
        unique_items.append(i)

Ответ 6

Сделайте это:

nums = [1, 1, 2, 2, 3, 3, 4, 4]
set_of_nums = set(nums)
unique_num_list = list(set_of_nums)

или даже это:

unique_num_list = sorted(set_of_nums)

Ответ 7

Начиная с Python 3.8 и введением выражений присваивания (PEP 572) (:= оператор), который дает возможность назвать результат выражения, мы могли бы ссылаться на уже увиденные элементы, обновляя переменную в пределах понимания списка:

# items = [1, 1, 2, 2, 3, 3, 4, 4]
acc = []; [acc := acc + [x] for x in items if x not in acc]
# acc = [1, 2, 3, 4]

Это:

  • Инициализирует список в соответствии с acc списком уже просмотренных элементов.
  • Для каждого элемента, это проверяет, если он уже часть acc список; а если нет:
    • добавляет элемент к acc (acc := acc + [x]) через выражение присваивания
    • и в то же время использует новое значение acc как сопоставленное значение для этого элемента