List 合并N个列表、跟踪重复项并按日期排序的最有效方法
我是Haskell的新手,我想知道合并任意数量项目列表的最有效方法。以下是示例数据:List 合并N个列表、跟踪重复项并按日期排序的最有效方法,list,sorting,haskell,merge,grouping,List,Sorting,Haskell,Merge,Grouping,我是Haskell的新手,我想知道合并任意数量项目列表的最有效方法。以下是示例数据: LIST 1: steve 2014-01-20 | cookies | steve LIST 2: chris 2014-02-05 | cookies | chris LIST 3: mark 2014-09-30 | brownies | mark 2014-03-30 | candy | mark 2014-05-12 | pie | mark LIST 4: anthony
LIST 1: steve
2014-01-20 | cookies | steve
LIST 2: chris
2014-02-05 | cookies | chris
LIST 3: mark
2014-09-30 | brownies | mark
2014-03-30 | candy | mark
2014-05-12 | pie | mark
LIST 4: anthony
2014-05-18 | cookies | anthony
2013-12-25 | fudge | anthony
LIST 5: andy
2014-10-04 | cookies | andy
LIST 7: john
2014-06-19 | pie | john
RESULTING LIST
2014-10-04 | cookies | andy chris steve anthony
2014-09-30 | brownies | mark
2014-06-19 | pie | john mark
2014-03-30 | candy | mark
2013-12-25 | fudge | anthony
请注意,这些列表都是以人为中心的,可能按日期排序,也可能不按日期排序,结果需要合并之前的列表,分组并创建一个列表,其中甜点是唯一的,但有一个吃甜点的人的列表,按日期倒序排序。解决问题的最有效方法是什么,在大多数情况下,无论是在haskell中还是在我认为的任何其他编程语言中都是不可回答的 一个更好的方法是思考,我如何解决这个问题(根本),并在你的脑海中保留一些原则
- 可测试性
- 抽象与表现
- 维修性
- 可读性
- 演出
data Name = Mark | Chris ...
deriving (Ord,Eq,Show)
data Items = Pie | Cookies ...
deriving (Ord,Eq,Show)
如果我还不知道haskell如何表示日期数据类型,我可以使用普通的字符串来建模,或者使用hoogle来查看是否已经存在日期类型
> hoogle date
...
Data.Time.Calendar...
...
因此,我想Data.Time.Calendar
模块似乎是一个很好的选择,我会看看它的文档,可以找到,或者如果您在本地安装该包,您可以使用haddock从源文件中自己生成它
我要做的下一步是对“数据库”进行建模。当然,有一些库可以处理sqly stuff或acid state—一个使用代数数据类型而不是数据库后端的数据库。但是为了更好地理解haskell,我会尝试重新发明轮子,使用元组列表或类似字典的集合,这在haskell中称为Map
。但是使用Map
时必须小心,并进行限定的导入,因为它提供的大多数函数都会与标准库中的函数发生名称冲突(Prelude)
为了对我的数据库进行建模,我将使用项作为键,使用日期元组和名称列表作为值,因为我想知道这是我的数据库,所以我将为此提供一个类型别名
type DB = M.Map Item (Date, [Name])
为了使用它,我将再次浏览一下地图
docu,并很高兴地找到插入
、空
和列表
。对于带有
函数的insertWith,我会考虑混合使用max
和list cons(:)
函数来创建新条目。
为了更好地了解整个过程,我会启动ghci
并导入合格的数据。映射为M
,然后使用M.Map String(String,[Int])
或诸如此类的示例在一级近似中对数据建模
对于结果,我必须按日期对地图的toList
进行排序,这只是一个小问题。mytoList myDb
的类型是[(项目,(日期,[名称])]
,因此通过fst.snd
和sortBy
进行排序应该会得到所需的结果
在我做了这么多之后,我会休息一下,阅读一些关于解析器的内容——让我所有的文件都与我的程序关联起来。用你最不信任的搜索引擎进行搜索,会发现一些值得一读的文章(Parser Parsec Haskell)。
如果这一切太复杂了,我会回去把我所有的类型都改成Strings
,希望在我有时间再次阅读有关解析器的内容之前,我不会有任何类型操作;-)
对于中间步骤中的任何问题,如果您提供具体的问题/问题描述,这里的人将乐于帮助您
如果所有这些性能都不够好,haskell提供的分析工具足以帮助我,但这是我要解决的最后一个问题。听起来你真的想要一个数据库。此外,在进行基准测试之前,我会小心尝试“性能最好”的算法。正如许多人在我之前所说的,早期优化是不好的。让它工作起来,然后运行探查器找出瓶颈所在,优化这些点,然后重复,直到您对性能满意为止。谢谢您的回复。我用java和C++编写了这个代码,并得到了合理的结果。我试过在博士后做这件事,但无论我做了什么,都很慢。(创造性索引等)
type DB = M.Map Item (Date, [Name])