В Swift, какой самый чистый способ получить последние два элемента в массиве?
Есть ли более чистый способ получить последние два элемента массива в Swift? В общем, я стараюсь избегать такого подхода, так как так легко быть по-одному с индексами. (С помощью Swift 1.2 для этого примера.)
// Swift -- slices are kind of a hassle?
let oneArray = ["uno"]
let twoArray = ["uno", "dos"]
let threeArray = ["uno", "dos", "tres"]
func getLastTwo(array: [String]) -> [String] {
if array.count <= 1 {
return array
} else {
let slice: ArraySlice<String> = array[array.endIndex-2..<array.endIndex]
var lastTwo: Array<String> = Array(slice)
return lastTwo
}
}
getLastTwo(oneArray) // ["uno"]
getLastTwo(twoArray) // ["uno", "dos"]
getLastTwo(threeArray) // ["dos", "tres"]
Я надеялся на что-то более близкое к удобству Python.
## Python -- very convenient slices
myList = ["uno", "dos", "tres"]
print myList[-2:] # ["dos", "tres"]
Ответы
Ответ 1
myList[-2:]
Да, у меня есть запрос на повышение, который запрашивает отрицательную индексную нотацию, и я предлагаю вам также создать файл.
Однако вы не должны делать это более сложным для себя, чем вам нужно. Встроенная глобальная функция suffix
выполняет именно то, что вам нужно:
let oneArray = ["uno"]
let twoArray = ["uno", "dos"]
let threeArray = ["uno", "dos", "tres"]
let arr1 = suffix(oneArray,2) // ["uno"]
let arr2 = suffix(twoArray,2) // ["uno", "dos"]
let arr3 = suffix(threeArray,2) // ["dos", "tres"]
Результат - это фрагмент, но вы можете принудить его к массиву, если вам нужно.
Ответ 2
В Swift 5, в соответствии с вашими потребностями, вы можете выбрать один из следующих шаблонов, чтобы получить новый массив из двух последних элементов массива.
# 1. Использование suffix(_:)
Array suffix(_:)
В Swift объекты, соответствующие протоколу Collection
, имеют метод suffix(_:)
. suffix(_:)
массива suffix(_:)
имеет следующее объявление:
func suffix(_ maxLength: Int) -> ArraySlice<Element>
Возвращает подпоследовательность, вплоть до заданной максимальной длины, содержащую последние элементы коллекции.
Использование:
let array = [1, 2, 3, 4]
let arraySlice = array.suffix(2)
let newArray = Array(arraySlice)
print(newArray) // prints: [3, 4]
# 2. Использование subscript(_:)
Array
subscript(_:)
В качестве альтернативы методу suffix(_:)
вы можете использовать subscript(_:)
Array
subscript(_:)
:
let array = [1, 2, 3, 4]
let range = array.index(array.endIndex, offsetBy: -2) ..< array.endIndex
//let range = array.index(array.endIndex, offsetBy: -2)... // also works
let arraySlice = array[range]
let newArray = Array(arraySlice)
print(newArray) // prints: [3, 4]
Ответ 3
В Swift 2 вы можете расширить CollectionType
. Вот пример (заимствование от Роба Напира):
extension CollectionType {
func last(count:Int) -> [Self.Generator.Element] {
let selfCount = self.count as! Int
if selfCount <= count - 1 {
return Array(self)
} else {
return Array(self.reverse()[0...count - 1].reverse())
}
}
}
Вы можете использовать его на любом CollectionType
. Здесь Array
:
let array = ["uno", "dos", "tres"]
print(array.last(2)) // [dos, tres]
Здесь CharacterView
:
let string = "looking"
print(string.characters.last(4)) // [k, i, n, g]
(Обратите внимание, что мой пример возвращает Array во всех случаях, а не в исходный тип коллекции.)
Ответ 4
Более общий ответ...
let a1 = [1,2,3,4,5]
let a2 = ["1","2","3","4","5"]
func getLast<T>(array: [T], count: Int) -> [T] {
if count >= array.count {
return array
}
let first = array.count - count
return Array(array[first..<first+count])
}
getLast(a1, count: 2) // [4, 5]
getLast(a2, count: 3) // ["3", "4", "5"]
Ответ 5
Вы можете сохранить явную проверку для подсчета массива с помощью трехпараметрической формы advance()
:
func getLast<T>(array: [T], count : Int) -> [T] {
let to = array.endIndex
// Decrease end index by `count`, but not beyond the start index:
let from = advance(to, -count, array.startIndex)
return Array(array[from ..< to])
}
getLast(oneArray, 2) // ["uno"]
getLast(twoArray, 2) // ["uno", "dos"]
getLast(threeArray, 2) // ["dos", "tres"]
getLast(threeArray, 4) // ["uno", "dos", "tres"]
Ответ 6
последние два элемента массива в Swift
EDIT: сначала проверяет, что myArray.count >= 2
let myArray2:Array? = myArray.count >= 2 ? [myArray[myArray.count-2], myArray[myArray.count-1]] : nil
Здесь он завернут в функцию, которая принимает массив и возвращает массив, содержащий последние два, или возвращает nil, если переданный массив не содержит по крайней мере двух элементов.
func getLastTwo(myArray:[String]) -> [String]? {
return myArray.count >= 2 ? [myArray[myArray.count-2], myArray[myArray.count-1]] : nil
}
Ответ 7
let items = [0, 2, 5, 3, 7, 6, 9, 10]
let count = items.count
let last2 = items[count - 2 ..< count] // [9, 10]
Ответ 8
Я сомневаюсь, что это сделает вас намного счастливее, но математика, безусловно, проще:
func getLastTwo(array: [String]) -> [String] {
if array.count <= 1 {
return array
} else {
return array.reverse()[0...1].reverse()
}
}
Обратите внимание, что reverse()
ленив, поэтому это не особенно дорого.
Ответ 9
в swift 5 вы можете использовать суффикс для получения объектов из последнего и префикс для получения объектов из первого, вот пример:
let exampleArray = ["first text", "second text", "third text"]
let arr1 = exampleArray.suffix(2) // ["second text", "third text"]
let arr2 = exampleArray.prefix(2) // ["first text", "second text"]
Результатом является срез, но вы можете привести его к массиву, если вам нужно.
Ответ 10
Решение Swift4:
let oneArray = ["uno"]
let twoArray = ["uno", "dos"]
let threeArray = ["uno", "dos", "tres"]
let arr1 = threeArray.suffix(from: threeArray.count-2) // ["dos", "tres"]
Другие примеры, поясняющие функциональность встроенной функции Swift - func suffix(from start: Int) → ArraySlice<Element>
:
let arr2 = oneArray.suffix(from: 0) // ["uno"]
let arr3 = twoArray.suffix(from: 0) // ["uno", "dos"]
let arr4 = twoArray.suffix(from: 1) // ["dos"]
let arr5 = threeArray.suffix(from: 1) // ["dos", "tres"]
let arr6 = threeArray.suffix(from: 2) // ["tres"]