我在Haskell中有两个列表。
包含字符串值的原始列表:
["Hello", "HELLO", "", "WORLD", "xxx", "world"]
包含整数值的索引列表,其中字符串在原始列表中都是大写:
[1,3]
我使用我创建的函数增加了索引列表中的所有值,并生成index2
列表,整体看起来像这样:
我的代码:
import Data.List
import Data.Char
import Data.Maybe
main = do
contents <- readFile "h.txt"
let original = lines (contents)
let allUpper = lines (map toUpper contents)
let onlyUpper = filter(/="") (intersect original allUpper)
let upperIndex = findIndices ('elem' onlyUpper) original
let index2 = (map increment upperIndex)
print index2
increment :: Int -> Int
increment x = x+1
在你的帮助下,我成功地走到了这一步。但是,由于我是初学者,我似乎不明白迭代如何工作。
我想要完成的是检查原始列表中相应的索引值(index2
)是否为空,如果它们为空,我想在index2
中删除它们
答案 0 :(得分:2)
我想要完成的事情是检查是否相应 索引值(在index2中)在原始列表中是空的,如果是 它们是空的,我想在index2中删除它们。
代码已过滤掉空元素!请看以下行:
let onlyUpper = filter(/="") (intersect original allUpper)
这一行做了两件事:
intersect original allUpper
),filter(/="")
)。如果空元素是指仅包含空格字符或没有空格的字符串,则可以使用:
filter (all isSpace)
我似乎不明白列表的迭代是如何工作的。
在Haskell中,列表是单链表:每个元素都包含一个值和对下一个值的引用。
因此,列表未编入索引:!!
运算符必须遍历每个元素才能访问特定元素,从而在处理直接访问时使列表效率低下。
当你向一个函数提交一个列表时,你只需给它第一个元素。
考虑到这些因素,当您处理列表时,必须避免通过索引访问元素。
我们的想法是创建在简单值上完成工作并将它们映射到元素列表的函数。看一下toUpper
函数:
toUpper :: Char -> Char
需要Char
并返回其大写版本(也是Char
)。
Haskell没有适用于toUpper
的{{1}}函数,您必须使用String
或map
之类的内容将<$>
应用于列表char(a toUpper
):
String
这个想法是拥有只能做一件特定事情的功能。对列表进行Upercasing和迭代是两回事。 map toUpper "ab" -- "AB"
toUpper <$> "ab" -- "AB"
函数是否需要知道它将大写的元素的索引?不!
你可能会问:但如果我的函数真的需要考虑元素的索引怎么办? (即:用于滤除偶数或奇数元素)。
你有两种方法可以考虑它:
toUpper
不是您需要使用的类型。也许Data.Map,Data.IntMap或Data.Vector更适合于任务(有关更多信息,请参阅这些模块),例如:
List
请注意,这也解决了您对增量函数的需求,因为索引是以您想要的任何值启动的。
要返回原始字符串,请写下:
let string = "abcde"
let indexedString = zip [1..] string
print indexedString -- [(1, 'a'), (2, 'b), (3, 'c), (4, 'd), (5, 'e)]
您需要使用map snd indexedString -- "abcde"
和fst
函数来处理中间类型,或使用模式匹配:
snd
考虑指数:
filter (\x -> snd x == 'b') indexedString -- [(2, 'b')]
map (\(i,s) -> (i, toUpper s)) indexedString -- [(1,'A'),(2,'B'),(3,'C'),(4,'D'),(5,'E')]
Haskell中已经存在let string = "abcde"
indexedString = zip [1..] string
upperEven (i, c) | even i = (i, toUpper c)
| otherwise = (i, c)
print $ map upperEven indexedString -- [(1,'a'),(2,'B'),(3,'c'),(4,'D'),(5,'e')]
print $ map snd $ map upperEven indexedString -- "aBcDe"
函数,它被称为increment
(它也是一个更通用的函数,适用于支持succ
类的所有类型,如Int,Char ...)< / p>
答案 1 :(得分:0)
为什么不对文件中的内容使用words :: String -> [String]
?如果每行有一个单词,则使用lines :: String -> [String]
将是另一种选择。
然后,如果我的问题得到解决,您可以编写以下内容来解决问题:
import Data.List (findIndices)
import Data.Char (isUpper)
allUpperOneBasedIndices :: String -> [Int]
allUpperOneBasedIndices = map succ . findIndices (all isUpper) . words