About
Swiftでは、配列内のポジションを知ることができる**enumarated()**とよばれる関数があります。
今回はこれについてまとめてました。
What it means
enumerateは *"一覧になったものに1つずつ名前を付ける"*という意味があります。
Available
iOS7.0から利用できます。
Swift3.0以前はSequenceTypeに**enumerate()でしたが,
Swift3からenumerated()**へと変更になりました。
Sources
Example.1
次のような例では配列の要素と一緒にインデックスが出力されます。
let fruits = ["Apples","Lemons","Oranges"]
var index = 0
for fruit in fruits {
print("Index: \(index), fruit: \(fruit)")
index += 1
}
// Index: 0, fruit: Apples
// Index: 1, fruit: Lemons
// Index: 2, fruit: Oranges
ループを繰り返すたびに+1を加えながら、fruitに対応するインデックスも表示されます。
しかし、これだと直接Int
を扱うので若干違和感がありますね。
そこで早速enumerated()
の出番です。
let fruits = ["Apples","Lemons","Oranges"]
for (index, fruit) in fruits.enumerated() {
print("Index: \(index), fruit: \(fruit)")
}
// Index: 0, fruit: Apples
// Index: 1, fruit: Lemons
// Index: 2, fruit: Oranges
Example.2
(index, fruit)
のように,型の異なる複数の値は, 以下のようにタプル(Tpule)で記述することが可能です。
let fruits = ["Apples","Lemons","Oranges"]
for item in fruits.enumerated() {
print(item.offset ,item.element)
}
// 0 Apples
// 1 Lemons
// 2 Oranges
それぞれドットを使って,インデックスは.offset
, 配列の要素は.element
で参照できます。
Example.3
for-inのような高速列挙を使わずmap
で表現する方法もあります。
let fruitList = fruits.enumerated().map { "\($0.0):\($0.1)" }
print(fruitList)
// ["0:Apples", "1:Lemons", "2:Oranges"]
あるいは
let fruitList = fruits.enumerated().map { "\($0.offset):\($0.element)" }
print(fruitList)
// ["0:Apples", "1:Lemons", "2:Oranges"]
そのため、map関数内クロージャーのように定義すれば便利ですね
let fruitList = fruits.enumerated().map { item in
print(item.offset, item.element)
}
// 0 Apples
// 1 Lemons
// 2 Oranges
Reference
AppleのAPIには次のように記載されています。
/// Returns a sequence of pairs (*n*, *x*), where *n* represents a
/// consecutive integer starting at zero, and *x* represents an element of
/// the sequence.
///
/// This example enumerates the characters of the string "Swift" and prints
/// each character along with its place in the string.
///
/// for (n, c) in "Swift".characters.enumerated() {
/// print("\(n): '\(c)'")
/// }
/// // Prints "0: 'S'"
/// // Prints "1: 'w'"
/// // Prints "2: 'i'"
/// // Prints "3: 'f'"
/// // Prints "4: 't'"
///
/// When enumerating a collection, the integer part of each pair is a counter
/// for the enumeration, not necessarily the index of the paired value.
/// These counters can only be used as indices in instances of zero-based,
/// integer-indexed collections, such as `Array` and `ContiguousArray`. For
/// other collections the counters may be out of range or of the wrong type
/// to use as an index. To iterate over the elements of a collection with its
/// indices, use the `zip(_:_:)` function.
///
/// This example iterates over the indices and elements of a set, building a
/// list of indices of names with five or fewer letters.
///
/// let names: Set = ["Sofia", "Camilla", "Martina", "Mateo", "Nicolás"]
/// var shorterIndices: [SetIndex<String>] = []
/// for (i, name) in zip(names.indices, names) {
/// if name.characters.count <= 5 {
/// shorterIndices.append(i)
/// }
/// }
///
/// Now that the `shorterIndices` array holds the indices of the shorter
/// names in the `names` set, you can use those indices to access elements in
/// the set.
///
/// for i in shorterIndices {
/// print(names[i])
/// }
/// // Prints "Sofia"
/// // Prints "Mateo"
///
/// - Returns: A sequence of pairs enumerating the sequence.
public func enumerated() -> EnumeratedSequence<Array<Element>>
extension SequenceType {
/// Returns a lazy `SequenceType` containing pairs (*n*, *x*), where
/// *n*s are consecutive `Int`s starting at zero, and *x*s are
/// the elements of `base`:
///
/// > for (n, c) in "Swift".characters.enumerate() {
/// print("\(n): '\(c)'")
/// }
/// 0: 'S'
/// 1: 'w'
/// 2: 'i'
/// 3: 'f'
/// 4: 't'
@warn_unused_result
public func enumerate() -> EnumerateSequence<Self>
}
Finally
書き方については,他にもいろんなパターンがあると思います。
他にも「こんな方法があるよ!」というアドバイスがございましたら、
是非ご教示頂けると幸いです。