如何在Swift中找到列表项的索引?

Ché*_*éyo 419 arrays swift

我试图通过搜索列表找到项目索引.有谁知道怎么做?

我看到有item index,list但我想要像python的东西list.StartIndex.

ssc*_*uth 792

由于swift在某些方面比面向对象更具功能性(并且Arrays是结构,而不是对象),因此使用函数"find"对数组进行操作,该函数返回一个可选值,因此请准备好处理nil值:

let arr:Array = ["a","b","c"]
find(arr, "c")!              // 2
find(arr, "d")               // nil
Run Code Online (Sandbox Code Playgroud)

Swift 2.0更新:

find使用Swift 2.0不再支持旧功能了!

使用Swift 2.0,Array可以使用在CollectionType(Array实现)扩展中定义的函数来查找元素索引:

let arr = ["a","b","c"]

let indexOfA = arr.indexOf("a") // 0
let indexOfB = arr.indexOf("b") // 1
let indexOfD = arr.indexOf("d") // nil
Run Code Online (Sandbox Code Playgroud)

此外,查找满足谓词的数组中的第一个元素是另一个扩展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
Run Code Online (Sandbox Code Playgroud)

请注意,这两个函数返回可选值,find如前所述.

Swift 3.0的更新:

请注意indexOf的语法已更改.对于符合Equatable您的物品,您可以使用:

let indexOfA = arr.index(of: "a")
Run Code Online (Sandbox Code Playgroud)

有关该方法的详细文档,请访问https://developer.apple.com/reference/swift/array/1689674-index

对于不符合Equatable您的数组项,您需要使用index(where:):

let index = cells.index(where: { (item) -> Bool in
  item.foo == 42 // test if this is the item you're looking for
})
Run Code Online (Sandbox Code Playgroud)

Swift 4.2的更新:

使用Swift 4.2时,index不再使用,而是将其分离firstIndexlastIndex进行更好的说明.因此,取决于您是否正在寻找项目的第一个或最后一个索引:

let arr = ["a","b","c","a"]

let indexOfA = arr.firstIndex(of: "a") // 0
let indexOfB = arr.lastIndex(of: "a") // 3
Run Code Online (Sandbox Code Playgroud)

  • 只需键入import Swift和Command-Click Swift (71认同)
  • 你在哪里了解了查找功能?我似乎无法找到任何"查找"或任何其他全局函数的文档 (21认同)
  • 来自OOP世界,我怎么能找到这种自由浮动函数? (14认同)
  • Johannes和@Rudolf - 使用Dash.app.它是用于浏览文档的OS X应用程序.它有一个Swift的语言参考,它有一个所有自由浮动函数的列表.易于过滤和搜索.没有它就活不下去. (5认同)
  • 我们可以删除 Swift 2 的东西吗?看到它很痛苦。 (5认同)
  • 它们似乎基本上没有记录.请参阅http://practicalswift.com/2014/06/14/the-swift-standard-library-list-of-built-in-functions/获取列表(但请注意,我没有检查列表是否完整或者是最新的). (4认同)
  • 仅供参考:如果您在自己定义的结构数组上使用`indexOf`,则结构必须符合`Equatable`协议. (4认同)
  • `arr.index(of:"element")`在Swift 3中不可用 (3认同)

Nik*_*iev 190

我认为值得一提的是,使用引用类型(class),您可能希望执行标识比较,在这种情况下,您只需要===在谓词闭包中使用标识运算符:


Swift 4/Swift 3:

let index = someArray.firstIndex{$0 === someObject}
Run Code Online (Sandbox Code Playgroud)

请注意,上面的语法使用尾随闭包语法,相当于:

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
Run Code Online (Sandbox Code Playgroud)


Swift 2 - index函数语法曾经是:

let indexOfPerson1 = people.firstIndex(where: {$0 === person1})
Run Code Online (Sandbox Code Playgroud)


*注意相关的和有用的评论通过paulbailey有关indexOf实现类型class,你需要考虑你是否应该用比较Equatable(标识符)或===(等式操作符).如果您决定使用匹配==,那么您可以简单地使用其他人建议的方法(==).

  • 如果`Person`实现了`Equatable`协议,那就不需要了. (7认同)
  • 对于那些想知道为什么.indexOf(x)不起作用的人来说,这是一个有用的帖子 - 这个解决方案是出乎意料的,但回想起来非常明显. (6认同)
  • 非常感谢这一点,但这对我来说根本不明显。我查看了文档,我真的不明白为什么在引用类型上使用 indexOf 时需要谓词闭包?感觉 indexOf 应该已经能够自己处理引用类型了。它应该知道它是引用类型而不是值类型。 (2认同)
  • 我收到:`二元运算符'==='不能应用于'_'和'Post'类型的操作数,`Post`是我的结构...任何想法? (2认同)

gwc*_*fey 80

你可以有filter一个带闭包的数组:

var myList = [1, 2, 3, 4]
var filtered = myList.filter { $0 == 3 }  // <= returns [3]
Run Code Online (Sandbox Code Playgroud)

你可以数一个数组:

filtered.count // <= returns 1
Run Code Online (Sandbox Code Playgroud)

因此可以判断,如果阵列包括通过组合这些你的元素:

myList.filter { $0 == 3 }.count > 0  // <= returns true if the array includes 3
Run Code Online (Sandbox Code Playgroud)

如果你想找到位置,我看不到花哨的方式,但你肯定可以这样做:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑

虽然我们正在努力,但为了一个有趣的练习,我们可以扩展Array到一个find方法:

extension Array {
    func find(includedElement: T -> Bool) -> Int? {
        for (idx, element) in enumerate(self) {
            if includedElement(element) {
                return idx
            }
        }
        return nil
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以这样做:

myList.find { $0 == 3 }
// returns the index position of 3 or nil if not found
Run Code Online (Sandbox Code Playgroud)

  • 为了在Swift 2/XCode 7下工作,您需要按如下方式修改它.用(includedElement:Element - > Bool)替换(includedElement:T - > Bool)并将枚举(self)更改为self.enumerate (4认同)
  • 只是想指出,你应该按照文档使用++ idx:"除非你需要i ++的特定行为,否则建议你在所有情况下使用++ i和--i,因为它们具有典型的预期修改i并返回结果的行为." (2认同)

Sar*_*ith 34

Swift 4.2

func firstIndex(of element: Element) -> Int?

var alphabets = ["A", "B", "E", "D"]
Run Code Online (Sandbox Code Playgroud)

例1

let index = alphabets.firstIndex(where: {$0 == "A"})
Run Code Online (Sandbox Code Playgroud)

例题

if let i = alphabets.firstIndex(of: "E") {
    alphabets[i] = "C" // i is the index
}
print(alphabets)
// Prints "["A", "B", "C", "D"]"
Run Code Online (Sandbox Code Playgroud)


Ser*_*nko 23

虽然indexOf()效果很好,但它只返回一个索引.

我正在寻找一种优雅的方法来获取满足某些条件的元素的索引数组.

以下是它的完成方式:

斯威夫特3:

let array = ["apple", "dog", "log"]

let indexes = array.enumerated().filter {
    $0.element.contains("og")
    }.map{$0.offset}

print(indexes)
Run Code Online (Sandbox Code Playgroud)

斯威夫特2:

let array = ["apple", "dog", "log"]

let indexes = array.enumerate().filter {
    $0.element.containsString("og")
    }.map{$0.index}

print(indexes)
Run Code Online (Sandbox Code Playgroud)


小智 14

Swift 4.2 中

.index(where:)改为.firstIndex(where:)

array.firstIndex(where: {$0 == "person1"})
Run Code Online (Sandbox Code Playgroud)


ZYi*_*iOS 12

对于自定义类,您需要实现Equatable协议.

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)
Run Code Online (Sandbox Code Playgroud)


小智 11

只需使用 firstIndex 方法。

array.firstIndex(where: { $0 == searchedItem })
Run Code Online (Sandbox Code Playgroud)


Zor*_*ayr 9

Swift 2更新:

sequence.contains(element):如果给定的序列(如数组)包含指定的元素,则返回true.

斯威夫特1:

如果你只想检查一个元素是否包含在一个数组中,也就是说,只需要一个布尔指示符,请使用contains(sequence, element)而不是find(array, element):

contains(sequence,element):如果给定的序列(例如数组)包含指定的元素,则返回true.

见下面的例子:

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.   
}
Run Code Online (Sandbox Code Playgroud)


Nai*_*hta 6

Swift 4 中,如果您要遍历 DataModel 数组,请确保您的数据模型符合 Equatable Protocol ,实现 lhs=rhs 方法,然后才能使用 ".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
    }
}
Run Code Online (Sandbox Code Playgroud)

进而,

let index = self.photos.index(of: aPhoto)
Run Code Online (Sandbox Code Playgroud)


Gur*_*ngh 6

Swift4。如果您的数组包含[String:AnyObject]类型的元素。所以要找到元素的索引使用下面的代码

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)
Run Code Online (Sandbox Code Playgroud)

或者如果您想根据字典中的关键字找到索引。这里数组包含Model类的对象,并且我正在匹配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
Run Code Online (Sandbox Code Playgroud)


ric*_*ter 5

在Swift 2(使用Xcode 7)中,Array包括协议indexOf提供的方法CollectionType.(实际上,有两个indexOf方法 - 一个使用相等来匹配一个参数,另一个使用闭包.)

在Swift 2之前,像集合这样的泛型类型没有办法为从它们派生的具体类型(如数组)提供方法.所以,在Swift 1.x中,"index of"是一个全局函数......它也被重命名,所以在Swift 1.x中,调用了全局函数find.

也可以(但不是必须)使用indexOfObject来自NSArray......的任何其他更复杂的搜索方法,该方法在Swift标准库中没有等价物.Just import Foundation(或另一个传递Foundation的模块),投射你ArrayNSArray,你可以使用很多搜索方法NSArray.


Luc*_*nzo 5

斯威夫特 2.1

var array = ["0","1","2","3"]

if let index = array.indexOf("1") {
   array.removeAtIndex(index)
}

print(array) // ["0","2","3"]
Run Code Online (Sandbox Code Playgroud)

斯威夫特 3

var array = ["0","1","2","3"]

if let index = array.index(of: "1") {
    array.remove(at: index)
}
array.remove(at: 1)
Run Code Online (Sandbox Code Playgroud)

  • 你正在改变一个“让数组”?``self`` 的使用也有问题。 (3认同)

Kev*_*OUX 5

此解决方案中的任何一个都适合我

这是我对 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
        })
Run Code Online (Sandbox Code Playgroud)


Moh*_*diq 5

为了 (>= swift 4.0)

这是相当简单的。考虑以下Array对象。

var names: [String] = ["jack", "rose", "jill"]
Run Code Online (Sandbox Code Playgroud)

为了获得元素的索引rose,你所要做的就是:

names.index(of: "rose") // returns 1
Run Code Online (Sandbox Code Playgroud)

笔记:

  • Array.index(of:)返回一个Optional<Int>.

  • nil 意味着该元素不存在于数组中。

  • 您可能想要强制解包返回的值或使用 anif-let来绕过可选值。


Dwi*_*igt 5

在 Swift 4 中,可以使用firstIndex方法。使用==相等运算符通过其在数组中查找对象的示例id

let index = array.firstIndex{ $0.id == object.id }
Run Code Online (Sandbox Code Playgroud)
  • 请注意,此解决方案避免了您的代码需要符合Equitable 协议,因为我们比较的是属性而不是整个对象

另外,关于==vs的注释,===因为到目前为止发布的许多答案在用法上有所不同:

  • ==是等式运算符。它检查值是否相等。
  • ===是身份运算符。它检查一个类的两个实例是否指向同一个内存。这与相等不同,因为使用相同值独立创建的两个对象将被视为相等,使用 == 而不是 ===,因为它们是不同的对象。(来源

从 Swift 的文档中阅读更多关于这些运算符的信息是值得的。