使用Haskell将数据集相互进行功能比较

6

经过一年多的思考,我终于理解了Haskell,足以将其视为我的主要语言,适用于大部分通用编程需求。我非常喜欢它。

但是,我仍然在努力以函数式的方式完成非常特定的操作。

以下是一个简化的例子:

Set = [("Bob", 10), ("Megan", 7), ("Frank", 2), ("Jane", 11)]

我希望能够比较这些条目。对于像C或Python这样的语言,我可能会创建一些复杂的循环,但我不确定在函数式编程中哪种方法(map、fold、列表推导?)最好或最有效。
下面是我开始工作的代码示例:
run xs = [ someAlgorithm (snd x) (snd y) | x <- xs, y <- xs, x /= y ]

谓词(predicate)使列表推导式不会将条目与自身进行比较,但是该函数并不十分高效,因为它会比较已经比较过的条目。例如,它会比较Bob和Megan,然后再比较Megan和Bob。

如果您对如何解决此问题有任何建议,将不胜感激。


你说你想要比较它们,但没有说明你想用比较结果做什么。从你的示例中看来,你想要查看列表中两个不同元素的每个选择。是这样吗? - Joachim Breitner
是的,但不包括"反向"选择。我想要比较Bob和Megan,Bob和Frank,Bob和Jane,然后比较Megan和Frank,Megan和Jane,最后是Frank和Jane(我认为这样涵盖了所有组合)。这看起来像是可以用fold函数完成的,但我不确定。 - subtlearray
1个回答

8
如果您的数据类型有排序,您可以使用x < y而不是x /= y
另一种方法是使用tails避免比较同一位置的元素:
[ ... | (x:ys) <- tails xs, y <- ys]

这样做的效果是只选择原始列表中出现在x之后的项目y。如果您的列表包含重复项,您需要将其与之前的显式过滤器结合使用。


OP似乎想要查看所有的成对组合,忽略顺序,因此我认为排序没有帮助——这似乎是一个必然的n ** 2问题。但是,对于尾部建议的+1,我认为这是正确的答案。 - Jamey Sharp
@JameySharp:是的,我在那个问题上有点脑抽了。已经把那部分删除了 :) - hammar
这是一个非常简洁的解决方案!非常感谢您的时间和帮助。 - subtlearray
1
需要注意的是,模式(x:ys) <- tails xs在遍历到tails xs的最后一个元素[]时会失败,这并不是错误而是故意的。在列表推导中,模式匹配失败不会导致错误,而是跳过该元素。 - Joachim Breitner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接