A common pattern in getting both an object and it's index when using arrays is:
guard let objectAndIndex = array.enumerated().first(where: {$0.element == foo}) //etc..
The object that is returned by the array.enumerated().first
according to apple is an EnumeratedSequence
-- is there a shorter, more colloquial term anyone finds useful,
I guess tuple would be a good candidate?
guard let objectTuple = array.enumerated().first(where: {$0.element == foo}) //etc...
I personal don't like thinking or speaking the word tuple but it's at least short.
CodePudding user response:
The object that is returned by the
array.enumerated().first
according to apple is an EnumeratedSequence
No. The object that is returned by array.enumerated()
is an EnumeratedSequence. The object returned by array.enumerated().first
is an element of the EnumeratedSequence. That element is indeed a tuple (regardless of what words you may or may not like to say).
Note that this tuple is not, as your names imply, an object and its index. It is an object and its offset. They are not necessarily the same. This is why the elements of the tuple are labeled offset
and element
.
The reason there is no colloquial name for EnumeratedSequence is that no one in practice ever encounters one — because what you usually do is enumerate the EnumeratedSequence, yielding a series of tuples:
for tuple in "hello".enumerated() {
print(tuple.offset, "is", tuple.element)
}
CodePudding user response:
A “pair” is a common term for a two-element tuple. In fact, the EnumeratedSequence
documentation calls it a pair:
EnumeratedSequence
is a sequence of pairs (n, x), where ns are consecutiveInt
values starting at zero, and xs are the elements of a base sequence.
So maybe you would like objectPair
better than objectTuple
. Then again, to a native English speaker, objectPair
kind of implies two objects of the same type, not an object and an Int
. So maybe not.
Perhaps you'd be happier just destructuring the tuple instead of giving it a name:
guard let (offset, object) = array
.enumerated()
.first(where: { $0.element == x })
else {
return
}
If the array elements are also Int
, you can explicitly label the tuple members when destructuring so the compiler can verify your assignments:
guard let (offset: offset, element: object) = array
// ^^^^^^ ^^^^^^^
// These labels must match the labels returned by enumerated().
.enumerated()
.first(where: { $0.element == x })
else {
return
}
CodePudding user response:
If I were looking for a less cumbersome name for that EnumeratedSequence.Element
, I would lean towards a “tuple” ( 1 to both Rob and Matt). But, I generally avoid the naming issue entirely and decompose it into its constituent parts, namely a separate offset
and value
, e.g.
guard let (offset, value) = collection.enumerated().first(where: { $0.element == searchString }) else {
return
}
But be careful to not conflate that offset
with an index. Specifically, while I am sure it is not the case here, but if you ever start using subsequences (e.g., an array “slice”), an offset produced by enumerated()
and the collection’s index may not be the same thing. Consider:
let array = ["a", "b", "c", "d", "e"]
let collection = array[2...]
print(collection) // ["c", "d", "e"]
print(collection.indices) // 2..<5, i.e., [2, 3, 4], not [0, 1, 2] as you might expect
As a result, if your intent was to use that offset
as an index, it would not work as you might expect:
let searchString = "e"
guard let (offset, value) = collection.enumerated().first(where: { $0.element == searchString }) else {
return
}
print(offset) // 2
print(value) // e
print(collection[offset]) // c !!!
Be careful to not use this “offset” as an “index”. It works for a simple Array
, but not for all collections.
It just depends upon for what you are using this offset. If your intent is to retrieve an index that you can later use as a subscript into your collection, it is more prudent to use firstIndex
:
guard let index = collection.firstIndex(of: searchString) else {
return
}
print(index, collection[index]) // 4 e ... the index can be used to retrieve the value from the collection
Or:
guard let index = collection.firstIndex(where: { $0 == searchString }) else {
return
}
print(index, collection[index]) // again, 4 e