2015-10-10 2 views
0

Учитывая массив, содержащий любое количество объектов, как вы могли бы чисто и безопасно получить первые 3 элемента из него для хранения в новом массиве? Если массив не содержит не менее 3 элементов, он не должен запускать исключение во время выполнения, вместо этого он должен только добавить количество элементов в массиве к новому массиву.Хранить первые несколько элементов в массиве в другом массиве, если они существуют

Я думал, что это может работать, но он не будет компилировать в Xcode 7, и если это так, я не думаю, что будет вести себя спокойно, как я хочу:

let arr1 = [1, 2, 3, 4, 5] 
let arr2 = arr1[0..<3] 
//Expected: arr == [1, 2, 3] 

let arr1 = [1, 2] 
let arr2 = arr1[0..<3] 
//Expected: arr2 == [1, 2] 

let arr1 = [Int]() 
let arr2 = arr1[0..<3] 
//Expected: arr2 == [] 

Конечно всегда можно сделать что-то вроде этого, или вы можете использовать цикл for, но ни один из них не является чистым и кратким. Я хочу найти более быстрый способ.

let arr1 = [1, 2] 
var arr2 = [Int]() 
if photos.count > 0 { 
    arr2.append(arr1[0]) 
} 
if photos.count > 1 { 
    arr2.append(arr1[1]) 
} 
if photos.count > 2 { 
    arr2.append(arr1[2]) 
} 

ответ

3

Я думаю, что самый простой способ будет

let arr2 = arr1.prefix(3) 
+0

Как насчет диапазонов, таких как '3 .. <6'? –

+1

@AaronBrager оригинальный вопрос примерно первый три. – MirekE

+0

Идеально подходит для того, что мне нужно, просто красиво – Joey

0

Вы можете осуществить то, что вы хотите с расширением до Array:

extension Array { 
    func safeRange(range : Range<Int>) -> ArraySlice<Element> { 
     guard range.startIndex >= 0 && range.endIndex >= 0 else { 
      fatalError("Ranges with negative numbers aren't supported") 
     } 

     var shrinkingRange = range 

     while shrinkingRange.endIndex > shrinkingRange.startIndex + 1 { 
      if shrinkingRange.endIndex <= self.count { 
       return self[shrinkingRange] 
      } 

      shrinkingRange.endIndex = shrinkingRange.endIndex - 1 
     } 

     return [] 
    } 
} 

В примерах вы дали себя так, как ожидалось:

let arr1 = [1, 2, 3, 4, 5] 
let arr2 = arr1.safeRange(0..<3) 
//Expected: arr == [1, 2, 3] 

let arr3 = [1, 2] 
let arr4 = arr3.safeRange(0..<3) 
//Expected: arr2 == [1, 2] 

let arr5 = [Int]() 
let arr6 = arr5.safeRange(0..<3) 
//Expected: arr2 == [] 

Вы также можете использовать filter:

extension CollectionType where Generator.Element : Equatable, Index == Int { 
    func safeRange(range : Range<Int>) -> [Self.Generator.Element] { 
     return self.filter { 
      let index = self.indexOf($0)! 
      return index >= range.startIndex && index < range.endIndex 
     } 
    } 
} 

(. Это может потерпеть неудачу, если ваш массив содержит повторяющиеся элементы, так как indexOf возвращает индекс первого экземпляра)

+0

Это будет аккуратное расширение, чтобы обойти! Оверкилл для моих конкретных потребностей, но очень полезен для других, я уверен. – Joey

0

Другой подход заключается в использовании функции ...

import Swift 

let arr1 = [1, 2, 3, 4, 5] 
let arr2 = [1, 2] 
let arr3 = [Int]() 

func firstThree(data: [Int]) -> [Int] { 
    var results = [Int]() 
    for (index, number) in data.enumerate() { 
     if (index < 3) { 
      results.append(number) 
     } 
    } 
    return results 
} 

print(firstThree(arr1)) 
print(firstThree(arr2)) 
print(firstThree(arr3)) 

печатается:

[1, 2, 3] 
[1, 2] 
[] 

Немного лучше было бы использовать дженерики и получить N количество элементов:

func genericFirstItems<T>(array: [T], numberOfItems: Int) -> [T] { 
    var results = [T]() 

    for (index, item) in array.enumerate() { 
     if index < numberOfItems { 
      results.append(item) 
     } 
    } 
    return results 
} 

print(genericFirstItems(arr1, numberOfItems: 3)) 
print(genericFirstItems(arr2, numberOfItems: 3)) 
print(genericFirstItems(arr3, numberOfItems: 3)) 

Это имеет тот же результат.

[1, 2, 3] 
[1, 2] 
[] 
Смежные вопросы