首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Haskell制作PhoneBook

在Haskell制作PhoneBook
EN

Stack Overflow用户
提问于 2013-12-11 12:48:17
回答 1查看 515关注 0票数 2

因此,我有两个文件,其内容如下:

代码语言:javascript
复制
File 1:
  Tom 965432145  
  Bill 932121234

File 2:
  Steve 923432323  
  Tom 933232323

我希望将它们合并,并将结果输出写入名为“out.txt”的文件。我编写这个函数是为了处理重复文件(当同一名称不止一次出现时,它会选择最终文件中的数字)。

该函数称为选择:

代码语言:javascript
复制
choosing :: [String] −> Int −> Int −> Int
choosing ("Name_of_person":_) num1 _ = num1 
choosing _ num1 num2
    | num2 ‘div‘ 100000000 == 2 = num2
    | otherwise = num1

以下是我迄今为止根据技巧所做的工作:

我把这个问题分解成小函数,这样就更容易解决了。

代码语言:javascript
复制
import Text.Printf
import Text.Parsec
import Text.Parsec.String


choosing _ num1 num2
  | num2 `div` 100000000 == 2 = num2
  | otherwise = num1



parseNameNumber :: Parser (String, Integer)
parseNameNumber = do
spaces
name <- many1 letter
space
number <- fmap read $ many1 digit
return (name, number)

parseFile :: String -> IO ()
parseFile = do
result <- parseFromFile (parseNameNumber `sepBy` newline)
case result of
Left err  -> print err
Right res -> print res


quicksort :: Ord a => [a] -> [a]
quicksort []     = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
where
    lesser  = filter (< p) xs
    greater = filter (>= p) xs

mergeEntries :: [(String, Int)] -> [(String, Int)] -> [(String, Int)]
mergeEntries [] y = y
mergeEntries x [] = x
mergeEntries xl@(x@(xname, xphone):xs) yl@(y@(yname, yphone):ys)
   | xname < yname  = x : mergeEntries xs yl
   | xname == yname = choosing xname x y : mergeEntries xs yl
   | xname > yname  = y : mergeEntries xs yl


serializeEntries :: [(Int, Char)] -> [Char]
serializeEntries entries = concatMap (uncurry $ printf "%s %d\n") entries


main = do
  entries1 <- fmap parseFile $ readFile "in1.txt"
  entries2 <- fmap parseFile $ readFile "in2.txt"
  writeFile "out.txt" $ serializeEntries $ mergeEntries $ quicksort entries1 quicksort entries2

现在,我认为一切都是正确的,除了返回IO()而不是字符串的解析函数之外,我如何更改它?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-12-11 15:35:37

好的,首先我不明白函数choosing。你能用简单的英语解释一下它是如何选择数字的吗?我问你是因为你有两个自相矛盾的定义。你的第一个定义是:

代码语言:javascript
复制
choosing :: [String] −> Int −> Int −> Int
choosing ("Name_of_person":_) num1 _ = num1 
choosing _ num1 num2
    | num2 ‘div‘ 100000000 == 2 = num2
    | otherwise = num1

这在英语中的意思是“如果人名以文字字符串Name_of_person开头,总是选择第一个数字。否则,如果它在200000000 .299999999范围内,选择第二个数字;如果不是,选择第一个数字”。那是..。很奇怪,但也许有一个很好的理由。

然而,当你把整个模块放出来时,你就不会这么做了。在这里,您有两个关于choosing的完整定义,并且有效地说“始终选择第一个数字”,因为第一个模式(choosing name num1 _)总是匹配的。

因此,首先,找出您想要对choosing做什么。我怀疑你想要做的是注释掉第一个定义。

现在,关于合并。文件是否按人名排序?不是吗?然后,一旦您阅读了列表,就需要对它们进行排序,这样您就可以确定两个文件之间何时有匹配的名称。一旦列表被排序,您就必须进行排序的合并:

代码语言:javascript
复制
mergeEntries [] y = y
mergeEntries x [] = x
mergeEntries xl@(x@(xname, xphone):xs) yl@(y@(yname, yphone):ys)
   | xname < yname  = x : mergeEntries xs yl
   | xname == yname = -- You fill in this part, using choosing here
   | xname > yname  = -- You fill in this part

另外,您可以使用比列表(如Map)更好的数据结构,而不是排序,并使用fromListWithtoList。然而,如果这是家庭作业,可能不在练习的范围之内。

为了序列化..。我认为,一旦你做了你需要做的,在那里添加所有的空格-记住,名字和数字之间的空格和数字后面的换行符,你会没事的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20519572

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档