我想从列表列表中找到元素的位置。
例如,在给定列表中[[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 .. ?
我想以最有效的方式做到这一点。 感谢。
答案 0 :(得分:4)
好的,让我们打破这个。
如果您只对正常的整体列表感兴趣,那么
findPosition :: [Int] -> [Int]
你怎么能实现呢?好吧,呃,你需要输入你正在搜索的东西!
findPosition :: Int -> [Int] -> [Int]
好的,很酷。所以内置的elem
函数告诉你 if 你想要的元素是什么。但我们希望它是位置。又怎样?好吧,你可以用它的位置“标记”每个元素,如下所示:
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)]
这种方式可能不那么令人困惑。希望我已经给你足够的提示来解决这里的问题...
答案 1 :(得分:4)
您的类型签名错误。它应该是
findPosition :: Eq a => a -> [[a]] -> [(Int, Int)]
,因为
findPosition
限制为仅搜索Int
列表的列表---所有与内部元素相关的内容都是为了比较它们的相等性我也会findPosition
导致基于零的索引(由Haskell的标准列表函数使用)而不是您要求的基于一的索引。
所以我会有例如findPosition 8 [[1,2,3],[4,5,6],[7,8,9]] = [(2, 1)]
。
可悲的是,Hoogle知道没有Eq a => a -> [[a]] -> [(Int, Int)]
类型的函数。但搜索更简单的签名Eq a => a -> [a] -> [Int]
(搜索列表而不是列表列表的类似函数)指向elemIndices
。我们可以在findPosition
中使用它。
(哦,我太累了,不能完成这件事。希望它能让你深思熟虑。)
答案 2 :(得分:4)
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)]
答案 3 :(得分: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实例搜索所有可能的事件。