【问题标题】:Correct way to add an element to the end of a list?将元素添加到列表末尾的正确方法?
【发布时间】:2019-04-06 23:02:29
【问题描述】:

我在 thisHaskell 页面上阅读了有关在 List 末尾添加元素的信息。

使用该示例,我自己尝试了一下。鉴于以下List,我想在其末尾添加数字56

例子:

let numbers = [4,8,15,16,23,42] 
numbers ++ [56]

我被this 评论甩了:

将一个项目添加到列表的末尾是一个很好的练习,但通常 你不应该在真正的 Haskell 程序中这样做。很贵,而且 表示您正在以错误的顺序构建列表。有 通常是更好的方法。

Researching,我意识到我实际上正在做的是创建一个 List56 作为唯一的元素,我将它与 numbers list 结合起来。那是对的吗?

是否使用++ 将元素添加到List 末尾的正确方法?

【问题讨论】:

  • 你知道[a]是怎么定义的吗?这是一个嵌套结构,就像一个俄罗斯娃娃:列表的“末端”最好被认为是中心。如果您想添加一个新的最小玩偶,您需要打开每一层(O(n) 操作)。尝试自己实现++
  • “它很昂贵,表明您以错误的顺序构建列表。通常有更好的方法”部分非常重要。也许您应该先专注于如何以相反的顺序创建您的numbers 列表,然后像56 : numbers 一样进行操作以提高效率。

标签: list haskell


【解决方案1】:

++ [x] 是将元素添加到列表末尾的正确方法,但评论说的是您不应该将元素添加到列表末尾。

由于列表的定义方式,在末尾添加元素总是需要制作列表的副本。也就是说,

xs ++ ys

需要复制所有xs,但可以不加改变地重复使用ys

如果xs 只是一个元素(即我们添加到列表的开头),那没问题:复制一个元素几乎不需要任何时间。

但如果xs更长,我们需要花更多时间在++

如果我们重复这样做(即,我们通过不断地在末尾添加元素来构建一个大列表),那么我们需要花费大量时间来制作冗余副本。 (以这种方式构建一个 n 元素列表是一个 O(n2) 操作。)

如果您需要这样做,通常有更好的方法来构建您的算法。例如,您可以按相反的顺序构建您的列表(在开头添加元素),最后只调用reverse

【讨论】:

    【解决方案2】:

    这是正确的方法,因为所有的方法都必须减少到至少这么多的工作量。问题是想要追加到列表的末尾。这不是使用不可变链表可以有效执行的操作。

    更好的方法是弄清楚如何在不这样做的情况下解决您的特定问题。有很多潜在的方法。选择正确的取决于您正在做的事情的细节。也许你可以正确地使用懒惰。也许你最好反向生成列表,然后在最后反转一次。也许你最好使用不同的数据结构。这完全取决于您的具体用例。

    【讨论】:

      猜你喜欢
      • 2012-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-14
      • 2023-01-12
      • 2013-12-21
      相关资源
      最近更新 更多