我想从列表列表中找到元素的位置。
例如,在给定的列表 [[1,2,3],[4,5,6],[7,8,9]] 我想找到 8 的位置。函数应该返回 [[3,2 ]],即第三行第二列。如果列表是 [[1,2,8],[4,5,6],[7,8,9]] 那么它应该返回: [[1,3],[3,2]] 如果可以找不到那么它应该返回空列表
findPosition :: [[Int]] -> [(Int,Int)]
findPostion .. ?
我想以最有效的方式做到这一点。谢谢。
好的,让我们分解一下。
如果您只对正常的整数列表感兴趣,那么您有
findPosition :: [Int] -> [Int]
你怎么能实现呢?嗯,你需要输入你实际搜索的东西!
findPosition :: Int -> [Int] -> [Int]
嗯不错。所以内置elem
函数会告诉你你想要的元素是否在那里。但我们想要它的位置。又怎样?好吧,您可以用它的位置“标记”每个元素,如下所示:
label :: [x] -> [(Int, x)]
label = zip [0..]
现在我们可以使用它filter
来查找所有项目:
find :: (Eq x) => x -> [(Int, x)] -> [(Int, x)]
find x0 = filter (\ (n, x) -> x == x0)
但我们只想要实际位置,而不是x
s(此时它们都是相同的)。所以我们可以map fst
得到它。
全部组装起来,
findPosition :: Int -> [Int] -> [Int]
findPosition x0 = map fst . filter (\ (n, x) -> x == x0) . zip [0..]
那太棒了!但是你想要一个整数列表的列表,对吧?
我建议您更改您的需求规范以将每个“坐标”作为元组而不是列表返回。也就是说,让它这样
findPosition 8 [[1,2,8],[4,5,6],[7,8,9]] => [(1, 3), (3, 2)]
这样可能不会那么混乱。希望我已经给了你足够的提示来从这里弄清楚事情......
你的类型签名是错误的。它应该是
findPosition :: Eq a => a -> [[a]] -> [(Int, Int)]
因为
findPosition
于搜索 s 列表的列表Int
--- 它需要对内部元素做的就是比较它们是否相等我也会findPosition
产生从零开始的索引(Haskell 的标准列表函数使用的),而不是你要求的从一开始的索引。
所以我会有例如findPosition 8 [[1,2,3],[4,5,6],[7,8,9]] = [(2, 1)]
。
可悲的是,Hoogle 不知道带有 type 的函数Eq a => a -> [[a]] -> [(Int, Int)]
。但是搜索更简单的签名Eq a => a -> [a] -> [Int]
(搜索列表而不是列表的类似函数)将我们指向elemIndices
。我们可以在findPosition
.
(哦,我太累了,无法完成这个。希望它能让你深思。)
import Data.List
findPosition :: Int -> [[Int]] -> [(Int,Int)]
findPosition n xs = fp n xs 0
fp n [] i = []
fp n (x:xs) i = p x ++ fp n xs (i+1)
where
p x = zip (repeat i) (elemIndices n x)
例子:
findPosition 3 [[2,3,4,3],[4,5,2,3],[],[3,2,5,6,3],[2],[3]]
== [(0,1),(0,3),(1,3),(3,0),(3,4),(5,0)]
如果将函数的类型签名更改为:
findPosition :: (Eq a1, Num a) => a1 -> [[a1]] -> [(a, Int)]
您将有一个更通用的解决方案。例子:
findPosition 'a' ["car","small","caveat","big","","aah!"]
== [(0,1),(1,2),(2,1),(2,4),(5,0),(5,1)]
一个可能的解决方案:
import Control.Monad
findPosition :: Eq a => a -> [[a]] -> [(Int,Int)]
findPosition e ll = do
let annotate = zip [1..]
(i1,x) <- annotate ll
(i2,y) <- annotate x
guard $ y == e
return (i1,i2)
我们用索引注释列表和子列表中的每个元素,并使用 List 的 Monad 实例来搜索所有可能的出现。