Python: какой питонный способ выполнить этот цикл? - PullRequest
1 голос
/ 11 сентября 2009

Какой питонный способ выполнить этот цикл. Я пытаюсь выбрать случайный ключ, который вернет поддерево, а не корень. Следовательно: 'parent == None' не может быть правдой. «IsRoot == True» также не может быть правдой.

thekey = random.choice(tree.thedict.keys())
while (tree.thedict[thekey].parent == None)or(tree.thedict[thekey].isRoot == True):
        thekey = random.choice(tree.thedict.keys())
.......

edit: теперь работает

Ответы [ 8 ]

3 голосов
/ 11 сентября 2009
key = random.choice([key for key, subtree in tree.thedict.items()
                         if subtree.parent and not subtree.isRoot])

(Исправлено после комментариев и исправления вопроса)

3 голосов
/ 11 сентября 2009

получить случайное поддерево, которое не является корень

not_root_nodes = [key, node for key,node in tree.thedict.iteritems() if not ( node.parent is None or node.isRoot)]
item = random.choice( not_root_nodes )
1 голос
/ 11 сентября 2009

Я думаю, что это немного лучше:

theDict = tree.thedict

def getKey():
    return random.choice(theDict.keys())

theKey = getKey()

while theDict[thekey].parent in (None, True):
    thekey = getKey()

Что ты думаешь?

1 голос
/ 11 сентября 2009
thekey = random.choice(tree.thedict.keys())
parent = thedict[thekey].parent
while parent is None or parent.isRoot:
    thekey = random.choice(tree.thedict.keys())
    parent = thedict[thekey].parent
0 голосов
/ 11 сентября 2009

Лично мне не нравится повторение инициализации ключа перед циклом while, а затем снова внутри цикла. Это возможный источник ошибок; что произойдет, если кто-то отредактирует одну из двух инициализаций и забудет отредактировать другую? Даже если этого никогда не произойдет, любой, кто читает код, должен тщательно проверить, чтобы убедиться, что обе инициализации идеально совпадают.

Я бы написал так:

while True:
    thekey = random.choice(tree.thedict.keys())
    subtree = tree.thedict[thekey]
    if subtree.parent is not None and not subtree.isRoot:
        break

P.S. Если вы действительно хотите получить поддерево и не заботитесь о ключе, необходимом для поиска поддерева, вы можете даже сделать это:

while True:
    subtree = random.choice(tree.thedict.values())
    if subtree.parent is not None and not subtree.isRoot:
        break

Некоторым людям может не понравиться использование "while True:", но это стандартная идиома Python для "цикла навсегда, пока что-то не запустится break". ИМХО это простой, понятный идиоматичный Python.

P.P.S. Этот код действительно должен быть заключен в оператор if, который проверяет, что дерево имеет более одного узла. Если дерево имеет только корневой узел, этот код будет зацикливаться вечно.

0 голосов
/ 11 сентября 2009
thekey = random.choice(tree.thedict.keys())
parent = tree.thedict[thekey].parent
while parent is None or tree.thedict[thekey].isRoot:
    thekey = random.choice(tree.thedict.keys())
    parent = thedict[thekey].parent
0 голосов
/ 11 сентября 2009

Я думаю, что ваше состояние пока неверно:

Я думаю, вы ожидаете этого: tree.thedict[thekey].parent == None
должно быть равно этому: tree.thedict[thekey].parent.isRoot == True

Если фактически оба значения означают «этот узел не является корнем», вам следует изменить второе выражение на: tree.thedict[thekey].isRoot == True

Как написано, ваш условный тест говорит "пока этот узел является корнем ИЛИ родитель этого узла является корнем". Если ваша древовидная структура представляет собой один корневой узел с множеством конечных узлов, в этом случае следует ожидать бесконечный цикл.

Вот переписать:

thekey = random.choice(k for k in tree.thedict.keys() if not k.isRoot)
0 голосов
/ 11 сентября 2009
def is_root(v): 
  assert (v.parent != None) == (v.isRoot)
  return v.isRoot
  #note how dumb this function looks when you guarantee that assertion

def get_random_nonroot_key():
  while True:
    thekey = random.choice(tree.thedict.keys())
    value = tree.thedict[thekey]
    if not is_root(value): return key

или рефакторинг ответа Роберто Бонвалле

def get_random_nonroot_key():
  eligible_keys = [k for k, v in tree.thedict.items() if not is_root(v)]
  return random.choice(eligible_keys)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...