Как вернуть первые 5 объектов массива в Swift?

В Swift есть умный способ использования методов более высокого порядка в Array для возврата 5 первых объектов? Путем выполнения этого было сохранение индекса и for-loop через индекс инкремента массива до 5 и возврат нового массива. Есть ли способ сделать это с помощью filter, map или reduce?

Ответ 1

Безусловно, самый лучший способ получить первые N элементов массива Swift - использовать prefix(_ maxLength: Int):

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

Это имеет преимущество в том, чтобы быть безопасным. Если счетчик, который вы передаете prefix, больше, чем счетчик массива, он просто возвращает весь массив.

ПРИМЕЧАНИЕ: как указано в комментариях, Array.prefix фактически возвращает ArraySlice, а не Array. В большинстве случаев это не должно иметь значения, но если вам нужно присвоить результат типу Array или передать его методу, ожидающему параметр Array вам нужно будет принудительно преобразовать результат в тип Array: let first5 = Array(someArray.prefix(5))

Ответ 2

Update: Теперь можно использовать prefix для получения первых n элементов массива. Отметьте @mluisbrown answer для объяснения того, как использовать префикс.

Исходный ответ: Вы можете сделать это очень легко без filter, map или reduce, просто вернув диапазон вашего массива:

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

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

Ответ 3

С Swift 5, в соответствии с вашими потребностями, вы можете выбрать один из 6 следующих кодов игровой площадки, чтобы решить вашу проблему.


# 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:) метод 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:) индекс предпочтительнее prefix(upTo:).


# 4. Использование prefix(through:) метод 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

Ответ 6

Для получения первых 5 элементов массива все, что вам нужно сделать, - это отрезать массив, о котором идет речь. В Swift вы делаете это так: array[0..<5].

Чтобы сделать N первых элементов массива более функциональным и обобщаемым, вы можете создать метод расширения для этого. Например:

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

Ответ 7

Я немного изменил ответ Маркуса, чтобы обновить его для последней версии Swift, поскольку var внутри вашего объявления метода больше не поддерживается:

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

Ответ 8

Обновление для Swift 4:

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

Для быстрой 3:

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

Ответ 9

Swift 4 с сохранением типов массивов

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

Ответ 10

Простой и Простой

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

Ответ 11

Для массива объектов вы можете создать расширение из 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()]

Ответ 12

Swift 4

Чтобы получить первые N элементов массива Swift, вы можете использовать prefix(_ maxLength: Int):

Array(largeArray.prefix(5))