Вопрос по python – Генерировать из генераторов

2

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

Например, mygenerator (2) дает 5, 4 и 6. Примените mygenerator к каждому из этих чисел, снова и снова к полученным числам. Генератор всегда выдает большее число, чем переданное в качестве аргумента, и для двух разных чисел никогда не даст одно и то же число.

мой генератор (2): 4 5 мой генератор (4): 10 11 12 мой генератор (5): 9 300 500

Таким образом, набор (9,10,11,12,300,500) имеет «расстояние» 2 от исходного числа, 2. Если я применю его к числу 9, я получу набор чисел с расстоянием "3". из оригинала 2.

По сути, я хочу создать набор, который имеет заданное расстояние от заданного числа, и у меня возникают проблемы с выяснением, как это сделать в Python. Помощь очень ценится :)

Ваш Ответ

3   ответа
3

что наш генератор возвращает квадрат и куб с заданным числом таким образом, что он выдаст уникальный так что если мы хотим получить числа на расстоянии D в простейшем случае, мы можем рекурсивно получить числа на расстоянии D-1, а затем применить к ним генератор

def mygen(N):
    yield N**2
    yield N**3

def getSet(N, dist):
    if dist == 0:
        return [N]

    numbers = []
    for n in getSet(N, dist-1):
        numbers += list(mygen(n))

    return numbers

print getSet(2,0)
print getSet(2,1)
print getSet(2,2)
print getSet(2,3)

выход

[2]
[4, 8]
[16, 64, 64, 512]
[256, 4096, 4096, 262144, 4096, 262144, 262144, 134217728]
0

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

Так, например. с 2 в качестве начального аргумента ваша структура данных будет выглядеть примерно так

resDataSet = [[2], 
              [4, 5],
              [9, 10, 11, 12, 300 , 500]
              ...
             ]

Индекс строки должен дать вам расстояние, и вы можете использовать методы, такие как расширение, чтобы добавить больше данных в ваш список.

2

(в случае, если оно не помещается в памяти и т. Д.)

def grandKids(generation, kidsFunc, val):
  layer = [val]
  for i in xrange(generation):
    layer = itertools.chain.from_iterable(itertools.imap(kidsFunc, layer))
  return layer

Пример:

def kids(x): # children indices in a 1-based binary heap
  yield x*2
  yield x*2+1

>>> list(grandKids(3, kids, 2))
[16, 17, 18, 19, 20, 21, 22, 23]

Кстати, решение в Haskell:

grandKids generation kidsFunc val =
  iterate (concatMap kidsFunc) [val] !! generation
@John Y: itertools.chain не работает (хорошо). concat (xs) будет похож на цепочку (* xs). это оценит xs в кортеж и поэтому заставит его использовать много памяти.
Очевидно, что Python никогда не будет таким лаконичным, как Haskell, для такого рода проблем, но вы можете, по крайней мере, сохранить себе вспомогательную функцию concat, полагаясь на itertools.chain.
На самом деле нет необходимости определять какие-либо дополнительные функции,return reduce(lambda a, v: (x for v in a for x in kidsFunc(v)), xrange(generation), [val]) это однострочное тело для grandKids, использующее выражения генератора.
Отличный ответ! Спасибо ooboo
это интересно, но вы обманываете решение Python. Если бы мы написали функции Prelude для Haskell, которые вы используете в Python (и это не сложно), функция выглядела бы очень похоже: def grandKids (generation, kidsFunc, val): return takeN (iterate (частичный (concatMap, kidsFunc)) , [val]), generation) Не поймите меня неправильно, Haskell (и FP) - это чистая красота, мораль здесь в том, что мы можем извлечь пользу из его уроков при использовании других языков. Полный код:gist.github.com/406204

Похожие вопросы