【问题标题】:The most performant way to merge N lists, track duplicates, and sort them by date合并 N 个列表、跟踪重复项并按日期排序的最高效方式
【发布时间】:2014-05-08 21:25:58
【问题描述】:

我是 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
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

请注意,这些列表都是以人为中心的,可能按日期排序,也可能不排序,结果需要合并先前的列表,分组并创建一个列表,其中甜点是唯一的,但有一个组成人员的列表吃了,按日期倒序排列。

【问题讨论】:

  • 听起来你真的想要一个数据库。此外,我会警惕在基准测试之前尝试“最高性能”的算法。正如许多人在我之前所说的那样,早期优化是不好的。让它工作,然后运行分析器来找出瓶颈所在,优化这些点,然后重复直到你对性能感到满意。
  • 感谢您的回复。我已经用 Java 和 C++ 对此进行了编码,并得到了合理的结果。我已经尝试在 Postgres 中执行此操作,但无论我尝试了什么,它都非常缓慢。 (创意索引等)

标签: list sorting haskell merge grouping


【解决方案1】:

什么是解决问题最高效的方法,在大多数情况下,无论是在 haskell 还是我认为的任何其他编程语言中都无法回答。

更好的方法是思考,我怎样才能(完全)解决这个问题,并牢记一些原则。

  • 可测试性
  • 抽象和表现力
  • 可维护性
  • 可读性
  • 性能

也许我忘记了一些事情,但对于你的问题,我想给出一个提示列表

如果我事先知道所有项目和名称,我会使用代数数据类型来模拟这种情况

data Name  = Mark | Chris ...
           deriving (Ord,Eq,Show)
data Items = Pie | Cookies ...
           deriving (Ord,Eq,Show)

如果我还不知道 haskell 如何表示日期数据类型,我可以使用普通的旧 String 对其进行建模,或者我会使用 hoogle 来查看是否已经存在 date-thingy。

> hoogle date
...
Data.Time.Calendar...
...

所以我猜Data.Time.Calendar 模块似乎是一个不错的选择,我会查看它的文档,这些文档都可以在online 找到,或者如果你在本地安装包,你可以使用 haddock 从源文件。

下一步我将采取的方法是对“数据库”进行建模,当然存在用于处理 sqly 内容的库或酸状态使用代数数据类型而不是数据库后端的数据库。但是为了更好地掌握haskell,我会尝试重新发明轮子一次并使用元组列表或类似字典的集合,它在haskell中称为Map。但是使用Map 时必须小心并进行合格的导入,因为它提供的大多数函数会导致与标准库中的函数发生名称冲突(Prelude)。

import qualified Map as M

为了对我的数据库进行建模,我将使用 Items 作为键,使用日期元组和名称列表作为值,并且我想知道这是我的数据库,我会为此提供一个类型别名。

type DB = M.Map Item (Date, [Name])

为了使用它,我将再次浏览Map 文档并很高兴找到函数insertWithemptytoList。对于insertWith 函数,我会考虑将max 和list cons (:) 函数混合起来创建新条目。 为了更好地了解整个事情,我会启动ghciimport qualified Data.Map as M 并使用M.Map String (String,[Int]) 或诸如此类的一些示例来对我的数据进行初步近似建模。

对于结果,我必须按日期对我的地图的toList 进行排序,这只是一个小问题。我的toList myDb 的类型是[(Item,(Date,[Name]))],所以按fst.sndsortBy 排序应该会得到预期的结果。

在我完成了这么多之后,我会休息一下并阅读一些有关解析器的内容 - 将我的所有文件与我的程序关联起来。使用您最不信任的搜索引擎进行搜索会发现一些值得一读的文章(Parser Parsec Haskell)。 如果所有这些都太复杂了,我会返回并将所有类型更改为Strings,并希望在我有时间再次阅读有关解析器的信息之前我不会有任何类型;-)。

对于中间步骤中的任何问题,如果您提供具体问题/问题描述,这里的人员将很乐意为您提供帮助。

如果所有这些都不够性能,haskell 提供的分析工具足以帮助我,但这是我最后一个要解决的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多