Как применить функцию к массиву массивов с плавающей запятой?

Предположим, что у меня есть n массивов, где n - переменная (некоторое число больше 2, обычно меньше 10).

Каждый массив имеет k элементов.

У меня также есть массив длины n, который содержит набор весов, которые определяют, как я хотел бы линейно комбинировать все массивы.

Я пытаюсь создать высокопроизводительную функцию более высокого порядка для объединения этих массивов в F #.

Как я могу это сделать, так что я получаю функцию, которая принимает массив массивов (arrs - образец), массив весов (весов), а затем вычисляет взвешенную сумму на основе весов?

let weights = [|.6;;.3;.1|]

let arrs = [| [|.0453;.065345;.07566;1.562;356.6|] ; 
              [|.0873;.075565;.07666;1.562222;3.66|] ; 
              [|.06753;.075675;.04566;1.452;3.4556|] |]

спасибо за любые идеи.

Ответы

Ответ 1

Здесь одно решение:

let combine weights arrs =
  Array.map2 (fun w -> Array.map ((*) w)) weights arrs 
  |> Array.reduce (Array.map2 (+))

ИЗМЕНИТЬ

Вот некоторые (очень необходимые) объяснения того, как это работает. Логически мы хотим сделать следующее:

  • Примените каждый вес к соответствующей строке.
  • Добавьте вместе скорректированные по весу строки.

Две строки выше делают именно это.

  • Мы используем функцию Array.map2 для объединения соответствующих весов и строк; способ, которым мы их объединяем, состоит в том, чтобы умножить каждый элемент в строке на вес, который выполняется через внутренний Array.map.
  • Теперь у нас есть массив взвешенных строк и нужно добавить их вместе. Мы можем делать это один шаг за раз, сохраняя текущую сумму, добавляя каждый массив поочередно. То, как мы суммируем два массива поточечно, - это снова использовать Array.map2, используя (+) как функцию для объединения элементов из каждого. Мы помещаем это в Array.reduce, чтобы применить эту функцию добавления к каждой строке поочередно, начиная с первой строки.

Надеюсь, это разумный подход к проблеме, хотя стиль без надзора, по общему признанию, делает его несколько сложным для подражания. Однако обратите внимание, что это не особенно результативно; вместо того, чтобы создавать новые массивы с каждым приложением map, map2 и reduce, будет более эффективным. К сожалению, стандартная библиотека не содержит хороших аналогов этих операций, которые работают на месте. Было бы относительно легко создать такие аналоги, и они могли бы использоваться почти так же, как я сделал здесь.

Ответ 2

Что-то вроде этого сделало это для меня:

let weights = [|0.6;0.3;0.1|]

let arrs = [| [|0.0453;0.065345;0.07566;1.562;356.6|] ; 
              [|0.0873;0.075565;0.07666;1.562222;3.66|] ; 
              [|0.06753;0.075675;0.04566;1.452;3.4556|] |]

let applyWeight x y = x * y

let rotate (arr:'a[][]) = 
    Array.map (fun y -> (Array.map (fun x -> arr.[x].[y])) [|0..arr.Length - 1|]) [|0..arr.[0].Length - 1|]

let weightedarray = Array.map (fun x -> Array.map(applyWeight (fst x)) (snd x)) (Array.zip weights arrs)

let newarrs = Array.map Array.sum (rotate weightedarray)

printfn "%A" newarrs

Кстати, необходимо 0, предшествующее значению float.