【问题标题】:How to return first 5 objects of Array in Swift?如何在 Swift 中返回 Array 的前 5 个对象?
【发布时间】:2015-04-16 03:49:33
【问题描述】:

在 Swift 中,有没有一种巧妙的方法可以使用 Array 上的高阶方法返回前 5 个对象? obj-c 的做法是保存一个索引,并通过数组递增索引进行 for 循环,直到它为 5 并返回新数组。有没有办法用filtermapreduce 做到这一点?

【问题讨论】:

  • 参见my answer for Swift 4,它显示了最多6种不同的方式来返回Array的第一个n元素。

标签: arrays swift


【解决方案1】:

到目前为止,获取 Swift 数组的前 N ​​个元素的最简洁方法是使用 prefix(_ maxLength: Int)

let someArray = [1, 2, 3, 4, 5, 6, 7]
let first5 = someArray.prefix(5) // 1, 2, 3, 4, 5

这具有边界安全的好处。如果您传递给prefix 的计数大于数组计数,则它只返回整个数组。

注意: 正如 cmets 中所指出的,Array.prefix 实际上返回 ArraySlice,而不是 Array。在大多数情况下,这应该没有什么区别,但是如果您需要将结果分配给 Array 类型或将其传递给期望 Array 参数的方法,则需要将结果强制转换为 Array 类型:let first5 = Array(someArray.prefix(5))

【讨论】:

  • +1 这样一个糟糕的名字选择,恕我直言。数组有dropFirstdropLast,所以还不如有takeFirsttakeLast
  • 另外如果你需要first5是一个数组,写let first5 = Array(someArray.prefix(5))
  • @mluisbrown 抱歉,不能同意你的看法 :) 在我的项目 video = video.prefix(5) 在 Xcode 7.2 中导致编译错误 Cannot assign value of type 'ArraySlice<Video>' to type '[Video]'
  • video = Array(video.prefix(5))
  • @onmyway133 prefix 可能只是 Swift 2.x(我不记得它是否在 1.x 中),但它肯定存在于任何支持 Swift 2.x 的操作系统中,它是 iOS 7 及更高版本。 Swift 功能的可用性取决于 Swift 版本,而不是 iOS 版本。
【解决方案2】:

更新: 现在可以使用prefix 来获取数组的前n 个元素。查看@mluisbrown's answer 了解如何使用前缀。

原答案: 不用filtermapreduce,只需返回数组的范围即可:

var wholeArray = [1, 2, 3, 4, 5, 6]
var n = 5

var firstFive = wholeArray[0..<n] // 1,2,3,4,5

【讨论】:

  • 如果您只想要 Swift 数组中的第一个 n 项目,您可以使用 wholeArray.prefix(n) ,它具有边界安全的额外好处。如果n 大于数组大小prefix 则返回整个数组。
  • 如果wholeArray 没有比n 更多的元素,它将崩溃
  • @Crashalot 我不完全确定,但我认为当时我写答案的地方没有prefix 这样的东西。
  • 使用此代码获取前 5 个对象...这非常有效 [0,1,2,3,4,5].enumerated().flatMap{ $0
【解决方案3】:

使用 Swift 5,根据您的需要,您可以选择 以下 6 个 Playground 代码之一来解决您的问题。


#1。使用subscript(_:)下标

let array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
let arraySlice = array[..<5]
//let arraySlice = array[0..<5] // also works
//let arraySlice = array[0...4] // also works
//let arraySlice = array[...4] // also works
let newArray = Array(arraySlice)
print(newArray) // prints: ["A", "B", "C", "D", "E"]

#2。使用prefix(_:)方法

复杂度:O(1) 如果集合符合RandomAccessCollection;否则,O(k),其中 k 是要从集合开头选择的元素数。

let array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
let arraySlice = array.prefix(5)
let newArray = Array(arraySlice)
print(newArray) // prints: ["A", "B", "C", "D", "E"]

Apple 声明prefix(_:)

如果最大长度超过集合中的元素个数,则结果包含集合中的所有元素。


#3。使用prefix(upTo:)方法

复杂度:O(1)

let array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
let arraySlice = array.prefix(upTo: 5)
let newArray = Array(arraySlice)
print(newArray) // prints: ["A", "B", "C", "D", "E"]

Apple 声明prefix(upTo:)

使用prefix(upTo:) 方法等效于使用部分半开范围作为集合的下标。下标表示法优于prefix(upTo:)


#4。使用prefix(through:)方法

let array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
let arraySlice = array.prefix(through: 4)
let newArray = Array(arraySlice)
print(newArray) // prints: ["A", "B", "C", "D", "E"]

#5。使用removeSubrange(_:)方法

复杂度:O(n),其中n是集合的长度。

var array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
array.removeSubrange(5...)
print(array) // prints: ["A", "B", "C", "D", "E"]

#6。使用dropLast(_:)方法

复杂度:O(1) 如果集合符合RandomAccessCollection;否则,O(k),其中 k 是要删除的元素数。

let array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
let distance = array.distance(from: 5, to: array.endIndex)
let arraySlice = array.dropLast(distance)
let newArray = Array(arraySlice)
print(newArray) // prints: ["A", "B", "C", "D", "E"]

【讨论】:

    【解决方案4】:
    let a: [Int] = [0, 0, 1, 1, 2, 2, 3, 3, 4]
    let b: [Int] = Array(a.prefix(5))
    // result is [0, 0, 1, 1, 2]
    

    【讨论】:

      【解决方案5】:

      SWIFT 4

      另一种解决方案:

      一个简单的内联解决方案,如果您的数组太短也不会崩溃

      [0,1,2,3,4,5].enumerated().compactMap{ $0.offset < 3 ? $0.element : nil }
      

      但是用这个很好用。

      [0,1,2,3,4,5].enumerated().compactMap{ $0.offset < 1000 ? $0.element : nil }
      

      如果你这样做通常会崩溃:

      [0,1,2,3,4,5].prefix(upTo: 1000) // THIS CRASHES
      
      [0,1,2,3,4,5].prefix(1000) // THIS DOESNT
      

      【讨论】:

      • for swift3 [0,1,2,3,4,5].enumerated().flatMap{ $0.offset &lt; 1000 ? $0.element : nil }
      • 谢谢!如果你想更新,flatMap 现在在 Swift 4 中被称为 compactMap 用于数组压缩。
      【解决方案6】:

      要获取数组的前 5 个元素,您需要做的就是对相关数组进行切片。在 Swift 中,你可以这样做:array[0..&lt;5]

      为了使挑选数组的前 N ​​个元素更具功能性和通用性,您可以创建一个扩展方法来执行此操作。例如:

      extension Array {
          func takeElements(var elementCount: Int) -> Array {
              if (elementCount > count) {
                  elementCount = count
              }
              return Array(self[0..<elementCount])
          }
      }
      

      【讨论】:

        【解决方案7】:

        斯威夫特 4

        要获取 Swift 数组的前 N ​​个元素,您可以使用 prefix(_ maxLength: Int)

        Array(largeArray.prefix(5))
        

        【讨论】:

          【解决方案8】:

          我略微更改了 Markus 的回答,将其更新为最新的 Swift 版本,因为不再支持您的方法声明中的 var

          extension Array {
              func takeElements(elementCount: Int) -> Array {
                  if (elementCount > count) {
                      return Array(self[0..<count])
                  }
                  return Array(self[0..<elementCount])
              }
          }
          

          【讨论】:

            【解决方案9】:

            对于对象数组,您可以从 Sequence 创建扩展。

            extension Sequence {
                func limit(_ max: Int) -> [Element] {
                    return self.enumerated()
                        .filter { $0.offset < max }
                        .map { $0.element }
                }
            }
            

            用法:

            struct Apple {}
            
            let apples: [Apple] = [Apple(), Apple(), Apple()]
            let limitTwoApples = apples.limit(2)
            
            // limitTwoApples: [Apple(), Apple()]
            

            【讨论】:

              【解决方案10】:

              Swift 4 可以保存数组类型

              extension Array {
                  func take(_ elementsCount: Int) -> [Element] {
                      let min = Swift.min(elementsCount, count)
                      return Array(self[0..<min])
                  }
              }
              

              【讨论】:

                【解决方案11】:

                简单明了

                extension Array {
                    func first(elementCount: Int) -> Array {
                          let min = Swift.min(elementCount, count)
                          return Array(self[0..<min])
                    }
                }
                

                【讨论】:

                  【解决方案12】:

                  Prefix 函数绝对是解决这个问题最有效的方法,但你也可以使用如下的 for-in 循环:

                  let array = [1,2,3,4,5,6,7,8,9]
                  let maxNum = 5
                  var iterationNumber = 0
                  var firstNumbers = [Int()]
                  if array.count > maxNum{
                    for i in array{
                      iterationNumber += 1
                      if iterationNumber <= maxNum{
                        firstNumbers.append(i)
                      }
                    }
                    firstNumbers.remove(at: 0)
                    print(firstNumbers)
                  } else {
                    print("There were not \(maxNum) items in the array.")
                  }
                  

                  这个解决方案占用了很多行代码,但是检查数组中是否有足够的项目来执行程序,然后继续并解决问题。 该解决方案使用了许多基本函数,包括 array.count,它返回数组中的项目数量,不是数组中最后一项的位置。它还使用array.append,它将东西添加到数组的末尾。最后,它使用array.remove,它删除了数组中具有指定位置的项。

                  我已经对其进行了测试,它至少适用于 swift 5。

                  【讨论】:

                    猜你喜欢
                    • 2017-12-05
                    • 2021-10-17
                    • 2019-11-10
                    • 2015-09-11
                    • 2021-03-02
                    • 2015-09-12
                    • 2015-09-12
                    • 2015-09-02
                    • 2015-08-29
                    相关资源
                    最近更新 更多