【问题标题】:Is there any difference at all between suffix(from:) and dropFirst(_:)?suffix(from:) 和 dropFirst(_:) 之间有什么区别吗?
【发布时间】:2017-03-13 00:29:02
【问题描述】:

我突然想到,在 Swift 中处理子序列时,

func suffix(from: Int) 似乎与 dropFirst(_:) 相同(显然,对于长度为“10”的数组,您只需将输入值从“3”更改为“7”。)

只是重复一遍。所以:当然,对于一个说 长度为 10 的数组。例如,我的意思是func suffix(from: Int) 带有“2”与dropFirst(_:) 带有“8” 相同。

类似upTo / through 似乎与dropLast(_:) 相同

除了方便还有什么区别

(可能在错误条件、性能或?)

我想知道,事实上,在 Swift 内部,一个或另一个是否只是通过调用另一个来实现的?

【问题讨论】:

标签: swift swift3 subsequence


【解决方案1】:

你说得对,它们是相互关联的,但是是的,它们是有区别的。来自文档:

let numbers = [1, 2, 3, 4, 5]
print(numbers.suffix(2))
// Prints "[4, 5]"
print(numbers.suffix(10))
// Prints "[1, 2, 3, 4, 5]"

let numbers = [1, 2, 3, 4, 5]
print(numbers.dropFirst(2))
// Prints "[3, 4, 5]"
print(numbers.dropFirst(10))
// Prints "[]"

在第一个示例中,suffix(2) 仅返回最后两个元素,而 dropFirst(2) 返回除前两个元素之外的所有元素。同样,它们的行为也不同。比序列长的参数很长。 (此外,后缀仅适用于有限序列。)

同样带有前缀和 dropLast。另一种思考方式,对于长度为 n 的序列,prefix(k) == dropLast(n-k),其中 k

【讨论】:

  • 坚持住科林! (请注意我在问题中以粗体显示的新示例。)在您的示例中,要从后缀变为 dropFirst,您将使用“2”然后更改为“3”。 “10”您将更改为“0”。 (嗯,“-5”,但我们可以理解在这种转换中将其设为“0”。)它们会看起来是相同的。
  • 要清楚!你看到你的最后一句话:“另一个............”这实际上正是我要问的:它们实际上是一样的吗,prefix(k) === dropLast(nk) ??
  • 我不确定用相同参数产生不同输出的函数是如何相同的?
  • 嘿@Co​​linBarrett! - 对,当然我的意思是简单地映射相关论点。无论如何,上面的 Rob 似乎已经回答了这个问题 - 是的,它们是相同的,它们称为相同的基质。
  • @ColinBarrett 请注意,您的回答是在谈论 suffix(_:),而不是 suffix(from:)——这是 OP 所要求的。
【解决方案2】:

IMO 最大的不同是 dropFirst() 不会将您的代码暴露给超出范围的索引错误。因此,您可以安全地在空数组上使用 dropFirst 的任何一种形式,而 prefix / suffix 方法可能会在空数组或超出范围的参数时崩溃。

所以dropFirst() FTW 如果您在指定的元素多于可用元素而不是崩溃时更喜欢空数组结果,或者如果您不想/需要检查以确保您的索引be using 小于array.count

从概念上讲,我认为这对于命名的操作是有意义的,因为first 是一个可选类型的属性,它返回第一个元素如果存在。说dropFirst(3) 的意思是“删除可能存在的第一个元素,如果它存在,并且这样做三遍”

【讨论】:

  • 等一下 - 这太棒了,但不幸的是,dropFirst() 立即(并且完全愚蠢地)在负数上崩溃。
  • @JoeBlow 我不认为它没有意义地减少崩溃。在数组上进行函数式链接时,例如array.filter{ $0 > 10 }.dropFirst(3).reduce{ + } 您不必在中间插入额外的命令式范围检查行。我认为对于许多链式操作案例,dropFirst() 是一个明显更好的选择。
  • @DanielHall 不需要UInt 实际上并不奇怪——Swift 团队建议使用Ints,即使已知值是非负的,因为它有助于互操作性。
  • @Hamish 我可以看到,但我认为互操作性最终将成为遗物,即使现在互操作性胜过类型检查,在这种情况下安全性也是......值得怀疑
  • 嘿 DH 和 H,我点击了一个赏金来表示感谢,愚蠢的所以你不能点击两个赏金。我认为你们两个在这里得出的见解非常令人难以置信。惊人的东西!干杯
【解决方案3】:

它们完全不同。

*与所有协议要求记录的时间复杂度一样,符合标准的类型可能具有具有较低时间复杂度的实现。例如,RandomAccessCollectiondropFirst(_:) 方法将在 O(1) 时间内运行。


然而,对于Array,这些方法只是发生表现相同(除了处理超出范围的输入)。

这是因为Array 有一个Int 类型的Index,它从0 开始并按顺序计数到array.count - 1,因此意味着删除第一个n 元素的子序列是从索引 n 开始的相同子序列

还因为ArrayRandomAccessCollection,这两种方法都将在 O(1) 时间内运行。

【讨论】:

  • Hamish,我想你在这里确实回答了这个问题:“但是,当涉及到 Array 时,这些方法 恰好 表现相同(除了处理超出范围的输入)。” 非常棒 - 谢谢。 Hamish 甚至是我侄子的名字 :)
  • 乐于帮助@JoeBlow :)
猜你喜欢
  • 1970-01-01
  • 2013-09-13
  • 2017-04-05
  • 2014-09-18
  • 2015-06-14
  • 2011-05-23
  • 2011-02-15
  • 2011-11-27
  • 2022-01-18
相关资源
最近更新 更多