문자열에 포함 된 문자의 인덱스를 정수 값으로 변환하고 싶습니다. 헤더 파일을 읽으려고 시도했지만에 대한 유형을 찾을 수 없지만 메서드 (예 Index
:)가있는 프로토콜을 준수하는 것으로 보입니다 .ForwardIndexType
distanceTo
var letters = "abcdefg"
let index = letters.characters.indexOf("c")!
// ERROR: Cannot invoke initializer for type 'Int' with an argument list of type '(String.CharacterView.Index)'
let intValue = Int(index) // I want the integer value of the index (e.g. 2)
도움을 주시면 감사하겠습니다.
답변
편집 / 업데이트 :
Xcode 11 • Swift 5.1 이상
extension StringProtocol {
func distance(of element: Element) -> Int? { firstIndex(of: element)?.distance(in: self) }
func distance<S: StringProtocol>(of string: S) -> Int? { range(of: string)?.lowerBound.distance(in: self) }
}
extension Collection {
func distance(to index: Index) -> Int { distance(from: startIndex, to: index) }
}
extension String.Index {
func distance<S: StringProtocol>(in string: S) -> Int { string.distance(to: self) }
}
놀이터 테스트
let letters = "abcdefg"
let char: Character = "c"
if let distance = letters.distance(of: char) {
print("character \(char) was found at position #\(distance)") // "character c was found at position #2\n"
} else {
print("character \(char) was not found")
}
let string = "cde"
if let distance = letters.distance(of: string) {
print("string \(string) was found at position #\(distance)") // "string cde was found at position #2\n"
} else {
print("string \(string) was not found")
}
답변
스위프트 4
var str = "abcdefg"
let index = str.index(of: "c")?.encodedOffset // Result: 2
참고 : 문자열 에 동일한 여러 문자가 포함 된 경우 왼쪽에서 가장 가까운 문자 만 가져옵니다.
var str = "abcdefgc"
let index = str.index(of: "c")?.encodedOffset // Result: 2
답변
encodedOffset
Swift 4.2 에서 더 이상 사용되지 않습니다. .
지원 중단 메시지 :
encodedOffset
가장 일반적인 사용법이 올바르지 않아 더 이상 사용되지 않습니다. 사용하다utf16Offset(in:)
동일한 동작을 달성하기 위해 합니다.
따라서 다음 utf16Offset(in:)
과 같이 사용할 수 있습니다 .
var str = "abcdefgc"
let index = str.index(of: "c")?.utf16Offset(in: str) // Result: 2
답변
index를 기반으로 문자열 연산을 수행하려면 기존 인덱스 숫자 방식으로는 수행 할 수 없습니다. swift.index는 indices 함수에 의해 검색되고 Int 유형이 아니기 때문입니다. String이 문자의 배열이지만 인덱스로 요소를 읽을 수는 없습니다.
이것은 실망 스럽습니다.
따라서 string의 모든 짝수 문자의 새 하위 문자열을 만들려면 아래 코드를 확인하십시오.
let mystr = "abcdefghijklmnopqrstuvwxyz"
let mystrArray = Array(mystr)
let strLength = mystrArray.count
var resultStrArray : [Character] = []
var i = 0
while i < strLength {
if i % 2 == 0 {
resultStrArray.append(mystrArray[i])
}
i += 1
}
let resultString = String(resultStrArray)
print(resultString)
출력 : acegikmoqsuwy
미리 감사드립니다
답변
다음은 값 Int
대신 s 로 하위 문자열의 경계에 액세스 할 수 있는 확장 입니다 String.Index
.
import Foundation
/// This extension is available at
/// https://gist.github.com/zackdotcomputer/9d83f4d48af7127cd0bea427b4d6d61b
extension StringProtocol {
/// Access the range of the search string as integer indices
/// in the rendered string.
/// - NOTE: This is "unsafe" because it may not return what you expect if
/// your string contains single symbols formed from multiple scalars.
/// - Returns: A `CountableRange<Int>` that will align with the Swift String.Index
/// from the result of the standard function range(of:).
func countableRange<SearchType: StringProtocol>(
of search: SearchType,
options: String.CompareOptions = [],
range: Range<String.Index>? = nil,
locale: Locale? = nil
) -> CountableRange<Int>? {
guard let trueRange = self.range(of: search, options: options, range: range, locale: locale) else {
return nil
}
let intStart = self.distance(from: startIndex, to: trueRange.lowerBound)
let intEnd = self.distance(from: trueRange.lowerBound, to: trueRange.upperBound) + intStart
return Range(uncheckedBounds: (lower: intStart, upper: intEnd))
}
}
이것이 기이함으로 이어질 수 있다는 점을 명심하십시오. 이것이 Apple이 그것을 어렵게 만들기로 선택한 이유입니다. (논쟁의 여지가있는 디자인 결정이긴하지만-어렵게 만들어 위험한 것을 숨기는 것 …)
Apple 의 String 문서에서 더 많은 것을 읽을 수 있지만, tldr은 이러한 “인덱스”가 실제로 구현에 따라 다르다는 사실에서 비롯된 것입니다. 그것들은 OS에 의해 렌더링 된 후 문자열에 대한 색인을 나타내 므로 사용중인 유니 코드 사양의 버전에 따라 OS에서 OS로 이동할 수 있습니다. 즉, 문자열에서 올바른 위치를 결정하기 위해 데이터에 대해 UTF 사양을 실행해야하므로 인덱스로 값에 액세스하는 것이 더 이상 상수 시간 작업이 아닙니다. 이러한 인덱스는 NSString에 의해 생성 된 값이나 기본 UTF 스칼라에 대한 인덱스와 함께 정렬되지 않습니다. 주의 사항 개발자.
답변
이와 같은 색인을 검색 할 때
⛔️ guard let index = (positions.firstIndex { position <= $0 }) else {
Array.Index로 처리됩니다. 컴파일러에게 정수를 원하는 단서를 제공해야합니다.
✅ guard let index: Int = (positions.firstIndex { position <= $0 }) else {