Câu trả lời:
Vì swift ở một số khía cạnh có nhiều chức năng hơn hướng đối tượng (và Mảng là cấu trúc, không phải đối tượng), sử dụng hàm "find" để hoạt động trên mảng, trả về giá trị tùy chọn, vì vậy hãy chuẩn bị để xử lý giá trị nil:
let arr:Array = ["a","b","c"]
find(arr, "c")! // 2
find(arr, "d") // nil
Cập nhật cho Swift 2.0:
find
Chức năng cũ không được hỗ trợ nữa với Swift 2.0!
Với Swift 2.0, Array
đạt được khả năng tìm chỉ mục của một phần tử bằng cách sử dụng hàm được xác định trong phần mở rộng của CollectionType
( Array
thực hiện):
let arr = ["a","b","c"]
let indexOfA = arr.indexOf("a") // 0
let indexOfB = arr.indexOf("b") // 1
let indexOfD = arr.indexOf("d") // nil
Ngoài ra, việc tìm phần tử đầu tiên trong một mảng đáp ứng một vị từ được hỗ trợ bởi một phần mở rộng khác của CollectionType
:
let arr2 = [1,2,3,4,5,6,7,8,9,10]
let indexOfFirstGreaterThanFive = arr2.indexOf({$0 > 5}) // 5
let indexOfFirstGreaterThanOneHundred = arr2.indexOf({$0 > 100}) // nil
Lưu ý rằng hai hàm này trả về các giá trị tùy chọn, như find
đã làm trước đó.
Cập nhật cho Swift 3.0:
Lưu ý cú pháp của indexOf đã thay đổi. Đối với các mặt hàng phù hợp với Equatable
bạn có thể sử dụng:
let indexOfA = arr.index(of: "a")
Một tài liệu chi tiết về phương pháp có thể được tìm thấy tại https://developer.apple.com/reference/swift/array/1689674-index
Đối với các mục mảng không phù hợp với Equatable
bạn sẽ cần sử dụng index(where:)
:
let index = cells.index(where: { (item) -> Bool in
item.foo == 42 // test if this is the item you're looking for
})
Cập nhật cho Swift 4.2:
Với Swift 4.2, index
không còn được sử dụng mà được tách ra firstIndex
và lastIndex
để làm rõ hơn. Vì vậy, tùy thuộc vào việc bạn đang tìm kiếm chỉ mục đầu tiên hoặc cuối cùng của mặt hàng:
let arr = ["a","b","c","a"]
let indexOfA = arr.firstIndex(of: "a") // 0
let indexOfB = arr.lastIndex(of: "a") // 3
indexOf
trên một loạt các cấu trúc mà bạn tự xác định, cấu trúc của bạn phải tuân thủ Equatable
giao thức.
tl; dr:
Đối với các lớp học, bạn có thể đang tìm kiếm:
let index = someArray.firstIndex{$0 === someObject}
Câu trả lời đầy đủ:
Tôi nghĩ rằng đáng để đề cập rằng với các loại tham chiếu ( class
) bạn có thể muốn thực hiện so sánh danh tính , trong trường hợp đó bạn chỉ cần sử dụng ===
toán tử nhận dạng trong bao đóng vị ngữ:
Swift 5, Swift 4.2:
let person1 = Person(name: "John")
let person2 = Person(name: "Sue")
let person3 = Person(name: "Maria")
let person4 = Person(name: "Loner")
let people = [person1, person2, person3]
let indexOfPerson1 = people.firstIndex{$0 === person1} // 0
let indexOfPerson2 = people.firstIndex{$0 === person2} // 1
let indexOfPerson3 = people.firstIndex{$0 === person3} // 2
let indexOfPerson4 = people.firstIndex{$0 === person4} // nil
Lưu ý rằng cú pháp trên sử dụng cú pháp đóng dấu theo dõi và tương đương với:
let indexOfPerson1 = people.firstIndex(where: {$0 === person1})
Swift 4 / Swift 3 - chức năng được gọi là index
Swift 2 - chức năng được gọi là indexOf
* Lưu ý nhận xét có liên quan và hữu ích của paulbailey về class
các loại triển khai Equatable
, nơi bạn cần xem xét liệu bạn nên so sánh bằng cách sử dụng ===
( toán tử nhận dạng ) hay ==
( toán tử đẳng thức ). Nếu bạn quyết định khớp bằng cách sử dụng ==
, thì bạn chỉ cần sử dụng phương thức được đề xuất bởi người khác ( people.firstIndex(of: person1)
).
Person
thực hiện Equatable
giao thức, điều này sẽ không cần thiết.
Binary operator '===' cannot be applied to operands of type '_' and 'Post'
, Post
cấu trúc của tôi ... có ý kiến gì không?
structs
(và enums
) là các loại giá trị, không phải loại tham chiếu. Chỉ các loại tham chiếu (ví dụ class
) có logic so sánh nhận dạng ( ===
). Kiểm tra các câu trả lời khác để biết phải làm gì structs
(về cơ bản bạn chỉ cần sử dụng array.index(of: myStruct)
, đảm bảo loại myStruct
tuân thủ Equatable
( ==
)).
Bạn có thể filter
một mảng với một bao đóng:
var myList = [1, 2, 3, 4]
var filtered = myList.filter { $0 == 3 } // <= returns [3]
Và bạn có thể đếm một mảng:
filtered.count // <= returns 1
Vì vậy, bạn có thể xác định xem một mảng có bao gồm phần tử của bạn hay không bằng cách kết hợp các phần sau:
myList.filter { $0 == 3 }.count > 0 // <= returns true if the array includes 3
Nếu bạn muốn tìm vị trí, tôi không thấy cách ưa thích, nhưng bạn chắc chắn có thể làm điều đó như thế này:
var found: Int? // <= will hold the index if it was found, or else will be nil
for i in (0..x.count) {
if x[i] == 3 {
found = i
}
}
BIÊN TẬP
Trong khi chúng ta đang ở đó, để có một bài tập thú vị, hãy mở rộng Array
để có một find
phương pháp:
extension Array {
func find(includedElement: T -> Bool) -> Int? {
for (idx, element) in enumerate(self) {
if includedElement(element) {
return idx
}
}
return nil
}
}
Bây giờ chúng ta có thể làm điều này:
myList.find { $0 == 3 }
// returns the index position of 3 or nil if not found
Array
để có một find
phương thức thực hiện những gì bạn muốn. Tôi chưa biết nếu đây là một thực hành tốt, nhưng nó là một thử nghiệm gọn gàng.
enumerate
để nó không còn áp dụng nữa, nhưng bạn hoàn toàn đúng.
func firstIndex(of element: Element) -> Int?
var alphabets = ["A", "B", "E", "D"]
Ví dụ 1
let index = alphabets.firstIndex(where: {$0 == "A"})
Ví dụ2
if let i = alphabets.firstIndex(of: "E") {
alphabets[i] = "C" // i is the index
}
print(alphabets)
// Prints "["A", "B", "C", "D"]"
Trong khi indexOf()
hoạt động hoàn hảo, nó chỉ trả về một chỉ mục.
Tôi đang tìm kiếm một cách thanh lịch để có được một loạt các chỉ mục cho các yếu tố thỏa mãn một số điều kiện.
Đây là cách nó có thể được thực hiện:
Swift 3:
let array = ["apple", "dog", "log"]
let indexes = array.enumerated().filter {
$0.element.contains("og")
}.map{$0.offset}
print(indexes)
Swift 2:
let array = ["apple", "dog", "log"]
let indexes = array.enumerate().filter {
$0.element.containsString("og")
}.map{$0.index}
print(indexes)
Đối với lớp tùy chỉnh, bạn cần thực hiện giao thức Equitable.
import Foundation
func ==(l: MyClass, r: MyClass) -> Bool {
return l.id == r.id
}
class MyClass: Equtable {
init(id: String) {
self.msgID = id
}
let msgID: String
}
let item = MyClass(3)
let itemList = [MyClass(1), MyClass(2), item]
let idx = itemList.indexOf(item)
printl(idx)
Cập nhật cho Swift 2:
Sequ.contains (phần tử) : Trả về true nếu một chuỗi đã cho (chẳng hạn như một mảng) có chứa phần tử đã chỉ định.
Swift 1:
Nếu bạn đang tìm kiếm chỉ để kiểm tra xem một phần tử có được chứa trong một mảng hay không, nghĩa là, chỉ cần lấy một chỉ báo boolean, sử dụng contains(sequence, element)
thay vì find(array, element)
:
chứa (chuỗi, phần tử) : Trả về true nếu một chuỗi đã cho (chẳng hạn như một mảng) chứa phần tử đã chỉ định.
Xem ví dụ dưới đây:
var languages = ["Swift", "Objective-C"]
contains(languages, "Swift") == true
contains(languages, "Java") == false
contains([29, 85, 42, 96, 75], 42) == true
if (contains(languages, "Swift")) {
// Use contains in these cases, instead of find.
}
trong Swift 4.2
.index (nơi :) đã được đổi thành .first Index (nơi :)
array.firstIndex(where: {$0 == "person1"})
Swift 4. Nếu mảng của bạn chứa các phần tử thuộc loại [String: AnyObject]. Vì vậy, để tìm chỉ mục của phần tử sử dụng mã dưới đây
var array = [[String: AnyObject]]()// Save your data in array
let objectAtZero = array[0] // get first object
let index = (self.array as NSArray).index(of: objectAtZero)
Hoặc Nếu bạn muốn tìm chỉ mục trên cơ sở khóa từ điển. Ở đây mảng chứa các đối tượng của lớp Model và tôi khớp với thuộc tính id.
let userId = 20
if let index = array.index(where: { (dict) -> Bool in
return dict.id == userId // Will found index of matched id
}) {
print("Index found")
}
OR
let storeId = Int(surveyCurrent.store_id) // Accessing model key value
indexArrUpTo = self.arrEarnUpTo.index { Int($0.store_id) == storeId }! // Array contains models and finding specific one
Swift 2.1
var array = ["0","1","2","3"]
if let index = array.indexOf("1") {
array.removeAtIndex(index)
}
print(array) // ["0","2","3"]
Swift 3
var array = ["0","1","2","3"]
if let index = array.index(of: "1") {
array.remove(at: index)
}
array.remove(at: 1)
let array
? Việc sử dụng self
là nghi vấn cũng có.
Trong Swift 4 , nếu bạn đang duyệt qua mảng DataModel của mình, hãy đảm bảo mô hình dữ liệu của bạn tuân thủ Giao thức tương đương, triển khai phương thức lhs = rhs và chỉ sau đó bạn mới có thể sử dụng ".index (of".
class Photo : Equatable{
var imageURL: URL?
init(imageURL: URL){
self.imageURL = imageURL
}
static func == (lhs: Photo, rhs: Photo) -> Bool{
return lhs.imageURL == rhs.imageURL
}
}
Và sau đó,
let index = self.photos.index(of: aPhoto)
Trong Swift 2 (với Xcode 7), Array
bao gồm một indexOf
phương thức được cung cấp bởi CollectionType
giao thức. (Trên thực tế, hai indexOf
phương thức mà một phương thức sử dụng đẳng thức để khớp với một đối số và một phương thức khác sử dụng một bao đóng.)
Trước Swift 2, không có cách nào cho các loại chung chung như bộ sưu tập cung cấp phương thức cho các loại cụ thể có nguồn gốc từ chúng (như mảng). Vì vậy, trong Swift 1.x, "index of" là một hàm toàn cục ... Và nó cũng được đổi tên, vì vậy, trong Swift 1.x, hàm toàn cầu đó được gọi làfind
.
Cũng có thể (nhưng không cần thiết) sử dụng indexOfObject
phương pháp từ NSArray
... hoặc bất kỳ phương pháp tìm kiếm meth phức tạp nào khác từ Tổ chức không có tương đương trong thư viện chuẩn Swift. Chỉ import Foundation
(hoặc một mô-đun khác nhập quá mức Foundation), Array
chuyển sang NSArray
và bạn có thể sử dụng nhiều phương pháp tìm kiếm trên NSArray
.
Bất kỳ giải pháp này làm việc cho tôi
Đây là giải pháp tôi có cho Swift 4:
let monday = Day(name: "M")
let tuesday = Day(name: "T")
let friday = Day(name: "F")
let days = [monday, tuesday, friday]
let index = days.index(where: {
//important to test with === to be sure it's the same object reference
$0 === tuesday
})
Bạn cũng có thể sử dụng thư viện chức năng Dollar để thực hiện một indexOf trên một mảng như http://www.dollarswift.org/#indexof-indexof
$.indexOf([1, 2, 3, 1, 2, 3], value: 2)
=> 1
Nếu bạn vẫn đang làm việc trong Swift 1.x
vậy hãy thử đi,
let testArray = ["A","B","C"]
let indexOfA = find(testArray, "A")
let indexOfB = find(testArray, "B")
let indexOfC = find(testArray, "C")
Đối với SWIFT 3, bạn có thể sử dụng một chức năng đơn giản
func find(objecToFind: String?) -> Int? {
for i in 0...arrayName.count {
if arrayName[i] == objectToFind {
return i
}
}
return nil
}
Điều này sẽ cho vị trí số, vì vậy bạn có thể sử dụng như
arrayName.remove(at: (find(objecToFind))!)
Hy vọng sẽ hữu ích
Chuyển 4
Giả sử bạn muốn lưu trữ một số từ mảng được gọi là cardButtons vào cardNumber, bạn có thể thực hiện theo cách này:
let cardNumber = cardButtons.index(of: sender)
người gửi là tên của nút của bạn
Trong Swift 4/5, sử dụng "First Index" để tìm chỉ mục.
let index = array.firstIndex{$0 == value}
Trong trường hợp ai đó có vấn đề này
Cannot invoke initializer for type 'Int' with an argument list of type '(Array<Element>.Index?)'
jsut làm điều này
extension Int {
var toInt: Int {
return self
}
}
sau đó
guard let finalIndex = index?.toInt else {
return false
}
Dành cho (>= swift 4.0)
Nó khá đơn giản. Hãy xem xét các Array
đối tượng sau đây .
var names: [String] = ["jack", "rose", "jill"]
Để có được chỉ mục của phần tử rose
, tất cả những gì bạn phải làm là:
names.index(of: "rose") // returns 1
Ghi chú:
Array.index(of:)
trả về một Optional<Int>
.
nil
ngụ ý rằng phần tử không có trong mảng.
Bạn có thể muốn hủy bỏ giá trị được trả về hoặc sử dụng giá trị if-let
xung quanh tùy chọn.