我对Haskell很新,并试图弄清楚我将如何编写一个函数来执行此操作,并且在梳理Google几个小时后,我对如何操作感到茫然。
在Haskell中给出以下两个列表
[(500,False),(400,False),(952,True),(5,False),(42,False)]
[0,2,3]
如何将第二个列表给出的每个位置的第一个列表的布尔值更改为输出的值为True
[(500,True),(400,False),(952,True),(5,True),(42,False)]
答案 0 :(得分:4)
我就是这样做的(假设要替换的索引列表已排序)。
首先,我们在要替换的索引列表和原始列表旁边添加索引列表。 然后我们递归列表,当我们点击下一个索引替换时,我们替换布尔值并递归所有三个列表的尾部。如果这不是索引 替换我们在整个替换索引列表和其他两个列表的尾部进行递归。
setTrue :: [Int] -> [(a, Bool)] -> [(a, Bool)]
setTrue is xs = go is xs [0..] -- "Index" the list with a list starting at 0.
where
go [] xs _ = xs -- If we're out of indexes to replace return remaining list.
go _ [] _ = [] -- If we run out of list return the empty list.
go indexes@(i:is) (x:xs) (cur:cs)
| i == cur = (fst x, True) : go is xs cs -- At the next index to replace.
| otherwise = x : go indexes xs cs -- Otherwise, keep the current element.
答案 1 :(得分:2)
这与Andrew的方法基本相同,但它没有使用额外的索引列表,而且更受传统map
的启发。请注意,与map
不同,提供的功能必须为a -> a
,且不能为a -> b
。
restrictedMap :: (a -> a) -> [Int] -> [a] -> [a]
restrictedMap f is xs = go f is xs 0
where
go f [] xs _ = xs
go f _ [] _ = []
go f ind@(i:is) (x:xs) n
| i == n = f x : go f is xs (n+1)
| otherwise = x : go f ind xs (n+1)
setTrue = restrictedMap (\(x,_) -> (x, True))
答案 2 :(得分:1)
描述中的直接翻译将是:
setIndexTrue f a = [(x, p || i `elem` f) | (i, (x,p)) <- zip [0..] a]
答案 3 :(得分:1)
或使用精彩的lens库:
setTrue :: [(a,Bool)] -> Int -> [(a,Bool)]
setTrue xs i = xs & ix i . _2 .~ True
setTrues :: [(a,Bool)] -> [Int] -> [(a,Bool)]
setTrues = foldl setTrue
答案 4 :(得分:0)
由于我未使用的方法未列出:
setTrue spots values = let
pattern n = replicate n False ++ [True] ++ Repeat False
toSet = foldl1 (zipWith (||)) $ map pattern spots
in zipWith (\s (v,o) -> (v, o || s)) toSet values