如何实现"where"(numpy.where(...))?

pt2*_*121 2 python haskell functional-programming scala numpy

我是一个功能性编程新手.我想知道如何在python,scala或haskell中实现numpy.where().一个好的解释对我有帮助.

ehi*_*ird 6

在Haskell中,对于n维列表来说,就像NumPy等效支持一样,需要一个相当高级的类型类构造,但是1维案例很容易:

select :: [Bool] -> [a] -> [a] -> [a]
select [] [] [] = []
select (True:bs) (x:xs) (_:ys) = x : select bs xs ys
select (False:bs) (_:xs) (y:ys) = y : select bs xs ys
Run Code Online (Sandbox Code Playgroud)

这只是一个简单的递归过程,依次检查每个列表的每个元素,并在每个列表到达结尾时生成空列表.(请注意,这些是列表,而不是数组.)

这是一个更简单但不太明显的一维列表实现,翻译NumPy文档中的定义(信用到joaquin指出):

select :: [Bool] -> [a] -> [a] -> [a]
select bs xs ys = zipWith3 select' bs xs ys
  where select' True x _ = x
        select' False _ y = y
Run Code Online (Sandbox Code Playgroud)

为了实现两参数的情况(返回条件为True的所有索引;归功于Rex Kerr指出这种情况),可以使用列表推导:

trueIndices :: [Bool] -> [Int]
trueIndices bs = [i | (i,True) <- zip [0..] bs]
Run Code Online (Sandbox Code Playgroud)

它也可以用现有的方式编写select,尽管没有多大意义:

trueIndices :: [Bool] -> [Int]
trueIndices bs = catMaybes $ select bs (map Just [0..]) (repeat Nothing)
Run Code Online (Sandbox Code Playgroud)

这是n维列表的三参数版本:

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}

class Select bs as where
  select :: bs -> as -> as -> as

instance Select Bool a where
  select True x _ = x
  select False _ y = y

instance (Select bs as) => Select [bs] [as] where
  select = zipWith3 select
Run Code Online (Sandbox Code Playgroud)

这是一个例子:

GHCi> select [[True, False], [False, True]] [[0,1],[2,3]] [[4,5],[6,7]]
[[0,5],[6,3]]
Run Code Online (Sandbox Code Playgroud)

但是,您可能希望在实践中使用正确的n维数组类型.如果你只是想select在一个特定的n的n维列表上使用,luqui的建议(来自这个答案的评论)是可取的:

在实践中,我会使用(zipWith3.zipWith3.zipWith3) select' bs xs ys(对于三维情况)而不是类型类黑客.

(添加的多种组合物zipWith3作为ñ增加.)


joa*_*uin 5

在python中numpy.where.__doc__:

If `x` and `y` are given and input arrays are 1-D, `where` is
equivalent to::

    [xv if c else yv for (c,xv,yv) in zip(condition,x,y)]
Run Code Online (Sandbox Code Playgroud)