Выражение Python Generator: как добавить условия И из цикла? - PullRequest
0 голосов
/ 17 февраля 2019

Имея следующую матрицу расстояний dist:

dist = [[[ 0, 0],
[ 5,  0],
[ 1,  0],
[ 1,  1],
[11,  3],
[ 3,  6],
[ 5,  5]],

[[ 5,  0],
[ 0,  0],
[ 6,  0],
[ 4,  1],
[ 6,  3],
[ 2,  6],
[10,  5]],

[[ 1,  0],
[ 6,  0],
[ 0,  0],
[ 2,  1],
[12,  3],
[ 4,  6],
[ 4,  5]],

[[ 1,  1],
[ 4,  1],
[ 2,  1],
[ 0,  0],
[10,  2],
[ 2,  7],
[ 6,  6]],

[[11,  3],
[ 6,  3],
[12,  3],
[10,  2],
[ 0,  0],
[ 8,  9],
[16,  8]],

[[ 3,  6],
[ 2,  6],
[ 4,  6],
[ 2,  7],
[ 8,  9],
[ 0,  0],
[ 8,  1]],

[[ 5,  5],
[10,  5],
[ 4,  5],
[ 6,  6],
[16,  8],
[ 8,  1],
[ 0,  0]]]

Мне нужно построить generator expression с AND условиями, подобными этим:

gexp = (dist[:, :, 0] <= 1) & (dist[:, :, 1] <= 2)

означает, что я хочузначение True, когда выполняются оба условия (для столбцов 0 и 1), как показано ниже (я напечатал его, переходя к синтаксису понимания списка):

[array([[ True, False,  True,  True, False, False, False],
       [False,  True, False, False, False, False, False],
       [ True, False,  True, False, False, False, False],
       [ True, False, False,  True, False, False, False],
       [False, False, False, False,  True, False, False],
       [False, False, False, False, False,  True, False],
       [False, False, False, False, False, False,  True]])]

У меня есть этот список столбцов:

columns = ['weight', 'height']

их пороги:

thresholds = {'weight': 1.0, 'height': 1.0}

и соответствующие им индексы:

indexes = {'weight': 0, 'height': 1}

Я пытаюсь построить выражение своего генератора следующим образом:

    dynamic_gexpr = [dist[:,:,indexes.get(column)] <= thresholds.get(column) for column in columns]

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

[array([[ True, False,  True,  True, False, False, False],
       [False,  True, False, False, False, False, False],
       [ True, False,  True, False, False, False, False],
       [ True, False, False,  True, False, False, False],
       [False, False, False, False,  True, False, False],
       [False, False, False, False, False,  True, False],
       [False, False, False, False, False, False,  True]]), array([[ True,  True,  True,  True, False, False, False],
       [ True,  True,  True,  True, False, False, False],
       [ True,  True,  True,  True, False, False, False],
       [ True,  True,  True,  True, False, False, False],
       [False, False, False, False,  True, False, False],
       [False, False, False, False, False,  True,  True],
       [False, False, False, False, False,  True,  True]])]

Ответы [ 3 ]

0 голосов
/ 17 февраля 2019

Это должно быть расширено, если вы добавите больше столбцов.arrays будет содержать массив для каждого условия.Каждый из них обрабатывается через reduce, который в свою очередь накапливает bitwise_and всех массивов.

import numpy as np
from functools import reduce
columns = ['weight', 'height']
thresholds = {'weight': 1.0, 'height': 1.0}
indexes = {'weight': 0, 'height': 1}

l = np.array(dist)
arrays = [(l[:, :, indexes[column]] <= thresholds[column]) for column in columns]
l2 = reduce(lambda a, acc : np.bitwise_and(a, acc), arrays)
print(l2)

Выходы:

[[ True False  True  True False False False]
 [False  True False False False False False]
 [ True False  True False False False False]
 [ True False False  True False False False]
 [False False False False  True False False]
 [False False False False False  True False]
 [False False False False False False  True]]
0 голосов
/ 17 февраля 2019

Как подсказывает @ 1Z10 в своих комментариях, np.reduce в конечном итоге будет вашим другом здесь.

Сначала вы должны построить матрицу логических значений, где каждая строка наивысшего уровня представляет собой сравнение подмассива с соответствующим емупорог.Затем просто используйте np.reduce и nb.logical_and в этой матрице, чтобы получить свой результат, независимо от количества сравнений:

dynamic_expr = np.logical_and.reduce(np.array(
    [dist[:, :, indexes[col]] <= thresholds[col]
     for col in columns]))
print(dynamic_expr)

вывод:

[[ True False  True  True False False False]
 [False  True False False False False False]
 [ True False  True False False False False]
 [ True False False  True False False False]
 [False False False False  True False False]
 [False False False False False  True False]
 [False False False False False False  True]]
0 голосов
/ 17 февраля 2019

Я использовал списочное понимание, чтобы применить условие, которое строит генератор, и наоборот, чувствовал себя неправильно.Во всяком случае, не уверен, что это то, что вы хотели.

x = ([second[0] <= 1 and second[1] <=2 for second in first] for first in dist)
for y in x:
    print(y)

Выходы:

[True, False, True, True, False, False, False]
[False, True, False, False, False, False, False]
[True, False, True, False, False, False, False]
[True, False, False, True, False, False, False]
[False, False, False, False, True, False, False]
[False, False, False, False, False, True, False]
[False, False, False, False, False, False, True]

для версии, которую вы почувствовали неправильно, если это то, что вы хотели

x = ((second[0] <= 1 and second[1] <=2 for second in first) for first in dist)

for y in x:
    print([next(y),next(y),next(y),next(y),next(y),next(y),next(y)])

которые выдают тот же

Теперь с написанием отдельной функции для сравнения

def compare(a,b):
    return all([a[i] <= b[i] for i in range(len(a))])

x = ((compare(second, [1,2]) for second in first) for first in dist)

for y in x:
    print([next(y),next(y),next(y),next(y),next(y),next(y),next(y)])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...