Haskell列表:替换列表中给定位置的元素

时间:2014-02-26 13:22:18

标签: haskell

我对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)]

5 个答案:

答案 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