Найти все комбинации только некоторых элементов массива

#python #numpy

#python #numpy

Вопрос:

У меня есть многомерный массив numpy и список объектов, некоторые значения массива numpy равны None

каким был бы наилучший способ найти все возможные комбинации, чтобы заполнить значения None объектами из списка?

например, если мой массив равен

 arr = [
    [1, None, 3],
    [9, 4, None],
]    
  

и список

 ls = [9, 8]
  

Я хочу найти эти

 arr = [
    [1, 9, 3],
    [9, 4, 8],
]  
arr = [
    [1, 8, 3],
    [9, 4, 9],
]
  

Ответ №1:

Одним из подходов было бы использовать маску для заполнения недопустимых записей массива значениями в ls столько раз, сколько существует перестановок ls .

Однако это можно сделать более надежным, установив длину этих перестановок на количество недопустимых записей в arr . Таким образом, мы также учитываем случай len(ls) > (x == None).sum() .

Перестановки могут быть получены с помощью itertools.permutations :

 def fill_combs(x, fill, replace=None):
    from itertools import permutations
    m = x == replace
    for i in permutations(fill, int(m.sum())):
        x_ = x.copy()
        x_[m] = np.array(i)
        yield x_.astype(int)
  

Пример запуска:

 arr = np.array([
    [1, None, 3],
    [9, 4, None],
])
ls = [9, 8]

list(fill_with_permut(arr, ls))
  

Вывод:

 [array([[1, 9, 3],
        [9, 4, 8]]), 
 array([[1, 8, 3],
        [9, 4, 9]])]
  

Или для большего ls :

 ls = [3,5,2]
list(fill_with_permut(arr, ls))

[array([[1, 3, 3],
        [9, 4, 5]]), 
 array([[1, 3, 3],
        [9, 4, 2]]), 
 array([[1, 5, 3],
        [9, 4, 3]]), 
 array([[1, 5, 3],
        [9, 4, 2]]), 
 array([[1, 2, 3],
        [9, 4, 3]]),
 array([[1, 2, 3],
        [9, 4, 5]])]
  

Ответ №2:

 def update(arr, items):
    count = 0
    for i, x in enumerate(arr):
        if None in x:
            arr[i][x.index(None)] = items[count]
            count  = 1
    return arr

import itertools
ls = [9, 8]
ls_ = list(itertools.permutations(ls))

for items in ls_:
    arr = [[1, None, 3],
           [9, 4, None]]
    print (update(arr,items))
  

Вывод:

 [[1, 9, 3], [9, 4, 8]]
[[1, 8, 3], [9, 4, 9]]
  

пример: ls = [9, 8, 15]

вывод:

 [[1, 9, 3], [9, 4, 8]]
[[1, 9, 3], [9, 4, 15]]
[[1, 8, 3], [9, 4, 9]]
[[1, 8, 3], [9, 4, 15]]
[[1, 15, 3], [9, 4, 9]]
[[1, 15, 3], [9, 4, 8]]