【问题标题】:Haskell List Comprehension order elements/tuplesHaskell List Comprehension order elements/tuples
【发布时间】:2018-05-07 18:51:49
【问题描述】:

我目前正在学习 Haskell,并且在 FP 方面绝对是初学者。

现在我正在尝试使用列表推导的不同方法。

 listComprehension  = [(a,b,c) | a <- xs, b <- xs, c <- ys, even c, c == a+b] ++
                      [(a,b,c) | a <- xs, b <- xs, c <- ys, even c, c == a-b]
                      where xs = [1..4]; ys = [(-100)..100]

为什么不说:

 listComprehension  = [(a,b,c) | a <- xs, b <- xs, c <- ys, even c, c == a+b || c == a-b]
                      where xs = [1..4]; ys = [(-100)..100]

?

我希望元素的排序与我的第一个示例完全相同。 我想要 c = a+b 的所有元素,然后是 c = a-b 的所有元素。

请注意,在我的第二个代码中,订单不是我想要的。我似乎无法弄清楚我是如何在列表理解中排序的,特别是当我有元组时..

谢谢!

【问题讨论】:

  • 您的第二个列表压缩比大多数都高效得多。它的输出是一个非常短的列表。-- 用 [(a,b,c) |(a,b,c)partition (\(a,b,c) -> c == a+b) lc1在一个元组中生成两个列表。– fp_mora 22 hours ag
  • 此外,当您可以设置它们时,从y 中选择值是多余的。结果是一样的。 let xs = [1..4] in [(a,b,c) | a &lt;- xs, b &lt;- xs, c &lt;- [(a-b),(a+b)], even c]

标签: haskell functional-programming list-comprehension


【解决方案1】:

在第一个生成器中的函数 (+),(-) 之间进行选择。

listComprehension =
   [(a,b,c) | f <- [(+),(-)], a <- xs, b <- xs, c <- ys, even c, c == f a b ]
   where xs = [1..4]; ys = [(-100)..100]

顺便说一句,这是一种低效的方法。而不是尝试每个c &lt;- ys,我们应该改为let c = f a b,然后检查-100 &lt;= c &amp;&amp; c &lt;= 100(和均匀度)是否。通过这种方式,我们使代码的速度提高了约 200 倍。

【讨论】:

  • 谢谢你这是完美的!我不知道您可以在列表理解中使用函数作为生成器。
  • @chi 只是出于好奇,你是如何测得 ~200 倍的加速?
  • @Marcel 当然,即使你不能使用函数,你仍然可以用普通数据达到同样的效果;例如[(a,b,c) | useAddition &lt;- [False, True], ..., c == if useAddition then a + b else a - b]。这里真正的见解是把你想要改变的东西作为第一个生成器放得最慢。
  • 好的,也很高兴知道。这肯定会在某些时候帮助我。再次感谢!
  • @jaroslawj 看起来没有经过测量,只是估计:对于 f、a 和 b 的每种组合,它减少了 200 次均匀性检查和比较。
【解决方案2】:

我之前在列表推导中使用过替代函数 ([even,odd])。我并不总是对他们最有效率感到满意。我看到的缺点是它们会通过源列表进行两次或多次传递。为此,我选择了一种不同的方法,不过,对于较小的数据集,效率并不是很重要的考虑因素。

这是我写的

lc xs ys = [[(a,b,c)|(a,b,c)<-ls,c==a+b] ++ [(a,b,c)|(a,b,c)<-ls,c==a-b]]
           where ls = [(a,b,c)| a<-xs, b<-xs, c<-ys, even c]

这比您的原始功能更快,也比其他答案更快。更引人注目的是,它使用的内存比两者都少。

从长列表中选择值是一回事,而仅从生成的值中设置它们是另一回事。

lc xs = [(a,b,c)|a<-xs,b<-xs,c<-[(a-b),(a+b)],even c]
partition (\(a,b,c) -> c == a+b) lc [1..4]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2014-01-14
    相关资源
    最近更新 更多