ChatGPT解决这个技术问题 Extra ChatGPT

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

我试图通过搜索 list 来查找 item index。有人知道该怎么做吗?

我看到有 list.StartIndexlist.EndIndex,但我想要 python 的 list.index("text") 之类的东西。


j
johndpope

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

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

使用 firstIndexlastIndex - 取决于您要查找项目的第一个索引还是最后一个索引:

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

let indexOfA = arr.firstIndex(of: "a") // 0
let indexOfB = arr.lastIndex(of: "a") // 3

您是从哪里了解到查找功能的?我似乎找不到任何有关“查找”或任何其他全局函数的文档
来自 OOP 世界,我应该如何找到这种自由浮动函数?
他们似乎在很大程度上没有记录。请参阅 practicalswift.com/2014/06/14/… 获取列表(但请注意,我没有检查列表是否完整或最新)。
Johannes 和@Rudolf - 使用 Dash.app。这是一个用于浏览文档的 OS X 应用程序。它有一个 Swift 语言参考,其中包含所有自由浮动函数的列表。易于过滤和搜索。没有它就活不下去。
仅供参考:如果您在自己定义的结构数组上使用 indexOf,则您的结构必须符合 Equatable 协议。
N
Nikolay Suvandzhiev

tl;博士:

对于课程,您可能正在寻找:

let index = someArray.firstIndex{$0 === someObject}

完整答案:

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

斯威夫特 5,斯威夫特 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

请注意,上述语法使用尾随闭包语法,等效于:

let indexOfPerson1 = people.firstIndex(where: {$0 === person1})


Swift 4 / Swift 3 - 曾经被称为 index 的函数

Swift 2 - 曾经被称为 indexOf 的函数

* 请注意 paulbailey 关于实现 Equatableclass 类型的相关且有用的 comment,您需要考虑是否应该使用 ===identity 运算符)或==相等运算符)。如果您决定使用==进行匹配,那么您可以简单地使用其他人建议的方法(people.firstIndex(of: person1))。


对于那些想知道为什么 .indexOf(x) 不起作用的人来说,这是一篇有用的帖子——这个解决方案是出乎意料的,但回想起来却非常明显。
非常感谢,但这对我来说并不明显。我查看了文档,我真的不明白为什么在引用类型上使用 indexOf 时需要谓词闭包?感觉 indexOf 应该已经能够自己处理引用类型了。它应该知道它是引用类型而不是值类型。
如果 Person 实现了 Equatable 协议,则不需要这样做。
我收到: Binary operator '===' cannot be applied to operands of type '_' and 'Post'Post 是我的结构......知道吗?
@DavidSeek,structs(和 enums)是值类型,而不是引用类型。只有引用类型(例如 class)具有标识比较逻辑(===)。查看其他答案以了解如何处理 structs(基本上您只需使用 array.index(of: myStruct),确保 myStruct 的类型符合 Equatable (==))。
g
gwcoffey

您可以filter 带有闭包的数组:

var myList = [1, 2, 3, 4]
var filtered = myList.filter { $0 == 3 }  // <= returns [3]

你可以计算一个数组:

filtered.count // <= returns 1

因此,您可以通过组合这些来确定数组是否包含您的元素:

myList.filter { $0 == 3 }.count > 0  // <= returns true if the array includes 3

如果您想找到该职位,我看不出花哨的方式,但是您当然可以这样做:

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
    }
}

编辑

在此过程中,作为一个有趣的练习,让我们扩展 Array 以拥有一个 find 方法:

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

现在我们可以这样做:

myList.find { $0 == 3 }
// returns the index position of 3 or nil if not found

为了有趣,我添加了另一个示例,在该示例中我扩展了内置 Array 以拥有一个 find 方法来满足您的需求。我还不知道这是否是一个好的做法,但这是一个很好的实验。
只是想指出,您应该按照文档使用 ++idx:“除非您需要 i++ 的特定行为,否则建议您在所有情况下都使用 ++i 和 --i ,因为它们具有典型的预期修改 i 并返回结果的行为。”
好决定。当您发布此内容时,我正在对其进行修改以使用 enumerate,因此它不再适用,但您是绝对正确的。
是的,我记得在我经历的一个例子中注意到了它。现在试着让自己养成这个习惯:)
为了在 Swift 2 / XCode 7 下工作,您需要按如下方式对其进行修改。将 (includedElement: T -> Bool) 替换为 (includedElement: Element -> Bool) 并将 enumerate(self) 更改为 self.enumerate
T
TheAlienMann

斯威夫特 5

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

var alphabets = ["A", "B", "E", "D"]

示例 1

let index = alphabets.firstIndex(where: {$0 == "A"})

示例 2

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

where 版本具有以下签名:func firstIndex(where: (Element) -> Bool) -> Int? 而且,由于 firstIndex 有一个尾随闭包,您可以为示例 1 编写:let index = alphabets.firstIndex { $0 == "A" } :-)
S
Serhii Yakovenko

虽然 indexOf() 运行良好,但它只返回一个索引。

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

这是如何完成的:

斯威夫特 3:

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

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

print(indexes)

斯威夫特 2:

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

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

print(indexes)

在子序列上使用它时要小心,偏移它与索引不同。并非所有集合索引都从零开始。请注意,这只适用于 Equatable 元素。 let indices = array.indices.filter { array[$0].contains("og") } 或使用 zip let indices = zip(array.indices, array).filter { $1.contains("og") }.map(\.0)
R
Ridho Octanio

在斯威夫特 4.2

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

array.firstIndex(where: {$0 == "person1"})

Z
ZYiOS

对于自定义类,您需要实现 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)

e
erdikanik

只需使用 firstIndex 方法。

array.firstIndex(where: { $0 == searchedItem })

错误:二元运算符“==”不能应用于两个“元素”操作数
D
Dwigt

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

let index = array.firstIndex{ $0.id == object.id }

请注意,此解决方案避免您的代码需要符合 Equitable 协议,因为我们正在比较属性而不是整个对象

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

== 是相等运算符。它检查值是否相等。

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

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


B
Bretsko

斯威夫特 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.   
}

G
Gurjinder Singh

Swift 4. 如果你的数组包含 [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)

或者如果您想根据字典中的键找到索引。这里数组包含模型类的对象,我正在匹配 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

N
Naishta

在 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
    }
}

接着,

let index = self.photos.index(of: aPhoto)

m
mzaink

对于(>= swift 4.0)

这很简单。考虑以下 Array 对象。

var names: [String] = ["jack", "rose", "jill"]

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

names.index(of: "rose") // returns 1

笔记:

Array.index(of:) 返回一个 Optional

nil 表示该元素不存在于数组中。

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


L
Luca Davanzo

斯威夫特 2.1

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

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

print(array) // ["0","2","3"]

斯威夫特 3

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

if let index = array.index(of: "1") {
    array.remove(at: index)
}
array.remove(at: 1)

你正在变异一个let arrayself 的使用也是有问题的。
C
Cœur

在 Swift 2(使用 Xcode 7)中,Array 包含由 CollectionType 协议提供的 indexOf 方法。 (实际上,有两个 indexOf 方法——一个使用相等来匹配参数,而 another 使用闭包。)

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

也可以(但不是必须)使用来自 NSArray... 的 indexOfObject 方法或来自 Foundation 的任何其他更复杂的搜索方法,这些方法在 Swift 标准库中没有等效项。只需 import Foundation(或传递导入 Foundation 的另一个模块),将您的 Array 转换为 NSArray,您就可以使用 NSArray 上的许多搜索方法。


K
Kevin ABRIOUX

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

这是我为 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
        })

E
Encore PTL

您还可以使用函数库 Dollar 对数组执行 indexOf,例如 http://www.dollarswift.org/#indexof-indexof

$.indexOf([1, 2, 3, 1, 2, 3], value: 2) 
=> 1

i
iCyberPaul

如果你还在使用 Swift 1.x

然后尝试,

let testArray = ["A","B","C"]

let indexOfA = find(testArray, "A") 
let indexOfB = find(testArray, "B")
let indexOfC = find(testArray, "C")

M
Marco

对于 SWIFT 3,您可以使用一个简单的函数

func find(objecToFind: String?) -> Int? {
   for i in 0...arrayName.count {
      if arrayName[i] == objectToFind {
         return i
      }
   }
return nil
}

这将给出数字位置,因此您可以使用 like

arrayName.remove(at: (find(objecToFind))!)

希望有用


K
Krunal Patel

在 Swift 4/5 中,使用“firstIndex”查找索引。

let index = array.firstIndex{$0 == value}

M
Menno

斯威夫特 4

对于参考类型:

extension Array where Array.Element: AnyObject {

    func index(ofElement element: Element) -> Int? {
        for (currentIndex, currentElement) in self.enumerated() {
            if currentElement === element {
                return currentIndex
            }
        }
        return nil
    }
}

A
Ahmed Safadi

万一有人遇到这个问题

Cannot invoke initializer for type 'Int' with an argument list of type '(Array<Element>.Index?)'

只是这样做

extension Int {
    var toInt: Int {
        return self
    }
}

然后

guard let finalIndex = index?.toInt else {
    return false
}

佚名

斯威夫特 4

假设您想将名为 cardButtons 的数组中的一个数字存储到 cardNumber 中,您可以这样做:

let cardNumber = cardButtons.index(of: sender)

sender 是您的按钮的名称