Как фильтровать по предикату по индексу в Repa
У меня есть два массива Repa a1
а также a2
и я хотел бы устранить все элементы в a2
для которого соответствующий индекс в a1
выше определенного порога. Например:
import qualified Data.Array.Repa as R -- for Repa
import Data.Array.Repa (Z (..), (:.)(..))
a1 = R.fromFunction (Z :. 4) $ \(Z :. x) -> [8, 15, 9, 14] ! x
a2 = R.fromFunction (Z :. 4) $ \(Z :. x) -> [0, 1, 2, 3] ! x
threshold = 10
desired = R.fromFunction (Z :. 2) $ \(Z :. x) -> [0, 2] ! x
-- 15 and 14 are above the threshold, 10
Один из способов сделать это с selectP
но я бы хотел не использовать это, так как он вычисляет массивы, и я хотел бы, чтобы мои массивы оставались в отложенном виде, если это возможно.
Другой способ с repa-array
, но stack solver
похоже не знает, как импортировать эту библиотеку с решателем nightly-2017-04-10
,
2 ответа
Один из способов решения этой проблемы заключается в том, что для создания массива Repa необходимо знать размер (extent
) массива при создании (например, fromFunction
), но в случае операции фильтрации невозможно узнать размер результирующего массива в repa без применения предиката порогового значения, по существу вычисляя значения результирующего массива.
Еще один способ посмотреть на это, D
elayed array - это простая функция от индекса до значения, которое подходит для большинства операций. Для фильтрации, хотя, когда вы применяете предикат, для того, чтобы найти значение по определенному индексу, вам теперь нужно знать все значения, которые предшествуют этому индексу в результирующем массиве, причина для любого местоположения, может быть значение, может быть не.
Vector package элегантно решает эту проблему с помощью потокового объединения, и repa-array, следующая версия Repa, которая все еще находится на экспериментальной стадии, похоже, пытается использовать аналогичный подход, за исключением расширения до более высоких измерений (я могу ошибаться, убежище присмотрелся).
Итак, краткий ответ: невозможно выполнить фильтрацию с помощью функционального объединения Repa. Или:
- придерживаться
selectP
- быстрее (вероятно), но менее эффективно для памяти (наверняка), или - поросенок обратно на
ifilter
отvector
пакет для последовательной фильтрации
Вы можете создать список пар с zip
, затем filter
с помощью функции предиката с типом (Int,Int) -> Bool
и, наконец, извлечь первый или второй элемент пары (в зависимости от того, какой из них вы хотите) с помощью map fst
или же map snd
соответственно. Все что вам для этого нужно в Prelude.
Я надеюсь, что этой информации достаточно, чтобы вы могли собрать все вместе. Если вы сомневаетесь, посмотрите на сигнатуры типов функций, которые я упомянул.