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

#python #python-3.x #list #algorithm #performance

#python #python-3.x #Список #алгоритм #Производительность

Вопрос:

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

 graph1 = [[0, 0, 0], [1, 0, 1], [2, 0, 0]]
graph2 = [[5, 0, 0], [1, 0, 1], [2, 0, 0]]
graph3 = [[2, 1, 0], [0, 0, 1], [0, 0, 0]]
graph4 = [[1, 0, 1], [9, 0, 0], [2, 0, 0]]

graphs = [graph1, graph2, graph3, graph4]

# TODO, what's the most efficient way to merge these lists into one single list where the final values are the max from each list maintaining position?
# desiredResultGraph = [[5, 1, 1], [9, 0, 1], [2, 0, 0]]
  

Обновленное решение, основанное на решении Марка Мейера, приведенном ниже:

 graph = np.ndarray(shape=(4, 3, 3), dtype=float, order='F')
graph[0] = [[0, 0, 1], [1, 0, 1], [2, 0, 0]]
graph[1] = [[0, 0, 1], [1, 0, 1], [2, 0, 0]]
graph[2] = [[5, 0, 0], [1, 0, 1], [2, 0, 0]]
graph[3] = [[2, 1, 0], [9, 0, 1], [0, 0, 0]]

PrintAndLog("graph of type "   str(type(graph))   " = "   str(graph))

resultGraph = graph.max(axis=0)
PrintAndLog("resultGraph of type "   str(type(resultGraph))   " = "   str(resultGraph))
  

Вывод:

 graph of type <class 'numpy.ndarray'> = 
[[[ 0.  0.  1.]
  [ 1.  0.  1.]
  [ 2.  0.  0.]]

 [[ 0.  0.  1.]
  [ 1.  0.  1.]
  [ 2.  0.  0.]]

 [[ 5.  0.  0.]
  [ 1.  0.  1.]
  [ 2.  0.  0.]]

 [[ 2.  1.  0.]
  [ 9.  0.  1.]
  [ 0.  0.  0.]]]
resultGraph of type <class 'numpy.ndarray'> = 
[[ 5.  1.  1.]
 [ 9.  0.  1.]
 [ 2.  0.  0.]]
  

Комментарии:

1. Вы можете сделать [[max(i) for i in zip(*v)] for v in zip(*graphs)] , но использование numpy , как правило, будет быстрее.

2. @AndrejKesely Понял. Итак, допустим, я начинаю с 4 отдельных массивов numpy вместо 4 отдельных списков, как я могу выполнить эту команду, которую вы предложили вместо объединения этих numpy arrarys?

Ответ №1:

Если вы работаете с большими наборами числовых данных, вам будет сложно превзойти производительность Numpy. И это упрощает такие вещи:

 import numpy as np

graph1 = [[0, 0, 0], [1, 0, 1], [2, 0, 0]]
graph2 = [[5, 0, 0], [1, 0, 1], [2, 0, 0]]
graph3 = [[2, 1, 0], [0, 0, 1], [0, 0, 0]]
graph4 = [[1, 0, 1], [9, 0, 0], [2, 0, 0]]

np.array([graph1, graph2, graph3, graph4]).max(axis = 0)
  

Результат:

 array([[5, 1, 1],
       [9, 0, 1],
       [2, 0, 0]])
  

Комментарии:

1. Мне нравится это решение за его элегантность. Но я действительно сомневаюсь, что это самый быстрый. np.array(….) необходимо создать новый массив, скопировав все данные из существующих массивов, и все это для выполнения тривиальной операции.

2. Я думаю, это справедливо @FrankYellin. Я подозреваю, что если OP действительно работает с массивными данными, в их интересах попытаться начать с массивов numpy с самого начала.

3. Я проверю это, а также посмотрю, что потребуется для преобразования моих списков python в массивы numpy везде, чтобы убедиться, что я не убиваю свою производительность.

4. @FrankYellin Итак, даже если я начну с numpy-массива вместо списка, если я использую np.array() и передам ему numpy-массивы, он все равно будет копировать (что неэффективно), верно?

5. @LampShade, если вы начинаете с массива numpy, это будет просто some_array.max(axis = 0) , что будет очень эффективно.