在Swift字符串中查找字符的索引

222

是时候承认失败了...

在Objective-C中,我可以使用类似以下的内容:

NSString* str = @"abcdefghi";
[str rangeOfString:@"c"].location; // 2

在Swift中,我看到了类似的东西:

var str = "abcdefghi"
str.rangeOfString("c").startIndex

...但是它只会给我一个 String.Index,我可以用它来对原始字符串进行下标访问,但无法提取位置。

顺便说一句,那个String.Index有一个私有ivar叫做_position,其中包含了正确的值。我只是不知道它如何被公开。

我知道我可以很容易地将其添加到String中。 我更好奇的是,这个新API中我错过了什么。


这是一个 GitHub 项目,其中包含了许多用于 Swift 字符串操作的扩展方法:https://github.com/iamjono/SwiftString - RenniePet
我找到的最佳实现在这里:https://dev59.com/g1wY5IYBdhLWcg3ws5oF#32306142 - Carlos García
你需要区分Unicode代码点和扩展字形簇吗? - Ky -
33个回答

4
如果您想要知道字符串中某个字符的位置,可以使用以下代码以int类型返回:
let loc = newString.range(of: ".").location

Swift 5: Range<String.Index>?类型的值没有成员location - Neph

3

这对我有用,

var loc = "abcdefghi".rangeOfString("c").location
NSLog("%d", loc);

这也起作用了。
var myRange: NSRange = "abcdefghi".rangeOfString("c")
var loc = myRange.location
NSLog("%d", loc);

这两个似乎都依赖于NSString的行为。在我的playground里,我使用了一个中间变量来存储字符串。var str = "abcdef"; str.rangeOfString("c").location会出现一个关于String.Index没有名为location的成员的错误... - Matt Wilding
1
它能够工作,只是因为“string”是NSString而不是Swift的String。 - gderaco

3

我知道这个已经过时了,并且已经有一个被接受的答案,但是你可以使用以下几行代码来找到字符串的索引:

var str : String = "abcdefghi"
let characterToFind: Character = "c"
let characterIndex = find(str, characterToFind)  //returns 2

这里有关于Swift字符串的其他重要信息Swift中的字符串

,请参考。


在 Swift 3 中不可用 find - AamirR

2

如果你仔细想一想,其实你并不需要确切的位置整数版本。范围甚至是字符串索引就足以在需要时获取子字符串:

let myString = "hello"

let rangeOfE = myString.rangeOfString("e")

if let rangeOfE = rangeOfE {
    myString.substringWithRange(rangeOfE) // e
    myString[rangeOfE] // e

    // if you do want to create your own range
    // you can keep the index as a String.Index type
    let index = rangeOfE.startIndex
    myString.substringWithRange(Range<String.Index>(start: index, end: advance(index, 1))) // e

    // if you really really need the 
    // Int version of the index:
    let numericIndex = distance(index, advance(index, 1)) // 1 (type Int)
}

对我来说最好的答案是:func indexOf(target: String) -> Int { return (self as NSString).rangeOfString(target).location } - YannSteph

2

Swift中的字符串变量类型与Objective-C中的NSString相比包含不同的函数。正如Sulthan所提到的,

Swift字符串没有实现RandomAccessIndex

您可以将类型为String的变量向下转换为NSString(在Swift中有效)。这将使您可以访问NSString中的函数。

var str = "abcdefghi" as NSString
str.rangeOfString("c").locationx   // returns 2

2
最简单的方法是:
在 Swift 3 中:
 var textViewString:String = "HelloWorld2016"
    guard let index = textViewString.characters.index(of: "W") else { return }
    let mentionPosition = textViewString.distance(from: index, to: textViewString.endIndex)
    print(mentionPosition)

1

扩展字符串:

{

//Fucntion to get the index of a particular string
func index(of target: String) -> Int? {
    if let range = self.range(of: target) {
        return characters.distance(from: startIndex, to: range.lowerBound)
    } else {
        return nil
    }
}
//Fucntion to get the last index of occurence of a given string
func lastIndex(of target: String) -> Int? {
    if let range = self.range(of: target, options: .backwards) {
        return characters.distance(from: startIndex, to: range.lowerBound)
    } else {
        return nil
    }
}

}


1

Swift 4完整解决方案:

OffsetIndexableCollection(使用Int索引的字符串)

https://github.com/frogcjn/OffsetIndexableCollection-String-Int-Indexable-

let a = "01234"

print(a[0]) // 0
print(a[0...4]) // 01234
print(a[...]) // 01234

print(a[..<2]) // 01
print(a[...2]) // 012
print(a[2...]) // 234
print(a[2...3]) // 23
print(a[2...2]) // 2

if let number = a.index(of: "1") {
    print(number) // 1
    print(a[number...]) // 1234
}

if let number = a.index(where: { $0 > "1" }) {
    print(number) // 2
}

在 Swift 5+ 中不起作用。 - joan

1

从思维角度来看,这可能被称为反转。你发现世界是圆的而不是平的。"你实际上不需要知道字符的索引就可以对其进行操作。" 作为一名C程序员,我也觉得这很难接受! 你的代码行 "let index = letters.characters.indexOf("c")!" 就足够了。例如,要删除c,你可以使用...(在playground中粘贴)

    var letters = "abcdefg"
  //let index = letters.rangeOfString("c")!.startIndex //is the same as
    let index = letters.characters.indexOf("c")!
    range = letters.characters.indexOf("c")!...letters.characters.indexOf("c")!
    letters.removeRange(range)
    letters

然而,如果您想要一个索引,您需要返回一个实际的INDEX,而不是作为Int值,因为使用Int值需要额外的步骤才能进行任何实际的操作。这些扩展将返回一个索引、特定字符的计数和范围,这个游乐场插件化的代码将演示。
extension String
{
    public func firstIndexOfCharacter(aCharacter: Character) -> String.CharacterView.Index? {

        for index in self.characters.indices {
            if self[index] == aCharacter {
                return index
            }

        }
        return nil
    }

    public func returnCountOfThisCharacterInString(aCharacter: Character) -> Int? {

        var count = 0
        for letters in self.characters{

            if aCharacter == letters{

                count++
            }
        }
        return count
    }


    public func rangeToCharacterFromStart(aCharacter: Character) -> Range<Index>? {

        for index in self.characters.indices {
            if self[index] == aCharacter {
                let range = self.startIndex...index
                return range
            }

        }
        return nil
    }

}



var MyLittleString = "MyVery:important String"

var theIndex = MyLittleString.firstIndexOfCharacter(":")

var countOfColons = MyLittleString.returnCountOfThisCharacterInString(":")

var theCharacterAtIndex:Character = MyLittleString[theIndex!]

var theRange = MyLittleString.rangeToCharacterFromStart(":")
MyLittleString.removeRange(theRange!)

1

String是NSString的桥接类型,因此添加

import Cocoa

将它添加到你的Swift文件中,并使用所有“旧”的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接