使用Swift查找字符串中第一个不重复的字符

4

这个代码可以在数组中找到重复的元素,但是我需要找到字符串中第一个不重复的字符。我一直在尝试着想出一种方法来实现这个功能,但是一直没有成功。下面是我目前最接近的代码。

var strArray = ["P","Q","R","S","T","P","R","A","T","B","C","P","P","P","P","P","C","P","P","J"]

println(strArray)

var filter = Dictionary<String,Int>()
var len = strArray.count
for var index = 0; index < len  ;++index {
var value = strArray[index]
if (filter[value] != nil) {
    strArray.removeAtIndex(index--)
    len--
}else{
    filter[value] = 1
}
}
println(strArray)

第一个不重复的还是第一个重复的? - Leo Dabus
你想要识别“P”吗? - Leo Dabus
我想找到一个字符串中第一个不重复的字符。例如:"DEFD -> E" - Bradley Scott Maskell
好的,你需要创建一个第二个数组,并逐一存储元素,直到找到重复项。 - Leo Dabus
@LeonardoSavioDabus 这个代码可以这样做吗?如果可以,你能给我一个更改的例子或者指导我找到答案的方向吗?感谢你的帮助。 - Bradley Scott Maskell
我已经添加了一些其他的解决方案,你可能会喜欢。 - Leo Dabus
10个回答

11
为了判断一个字符是否重复出现,需要遍历整个数组,并在字典中增加出现次数的计数:
let characters = ["P","Q","R","S","T","P","R","A","T","B","C","P","P","P","P","P","C","P","P","J"]

var counts: [String: Int] = [:]
for character in characters {
    counts[character] = (counts[character] ?? 0) + 1
}


let nonRepeatingCharacters = characters.filter({counts[$0] == 1})
// ["Q", "S", "A", "B", "J"]
let firstNonRepeatingCharacter = nonRepeatingCharacters.first!
// "Q"

1
@mattt 如果你想在1到1,000,000之间的数组中查找重复的整数,这个方法也适用吗? - Bradley Scott Maskell
1
我会尝试实现我的原始想法,即在数组逐渐增加时进行查找,并将其发布给您,以便您比较速度并选择最快的方法。但我认为他的解决方案可能是最快的。 - Leo Dabus
2
@BradleyScottMaskell 我不认为有什么问题。但是,如果你的问题仅限于在特定域中查找重复整数,那么更优雅的解决方案是创建一个位掩码,将第n位设置为1,表示数组中的每个数字n。这还具有结果排序的好处。 - mattt
2
@LeonardoSavioDabus 无论如何,都必须至少遍历整个数组,因此任何解决方案都将是O(n)。我预计在具有类似性能特征的解决方案之间的速度差异将是微不足道的。 - mattt
如果第一个不重复的字符出现在索引10处,而字符串长度为1000怎么办?在这种情况下,解决方案会更加复杂。 - Saranjith
这个使用字典方法如何保留顺序?难道字典不是一个无序集合吗? - amurray4

5
这里有一个简单的解决方案。
let inputString = "PQRSTPRATBCPPPPPCPPJ"

func nonRepeat (_ input: String) -> String {
    for char in input {
        if input.firstIndex(of: char) == input.lastIndex(of: char) {
            return String(char)
        }
    }
    return ""
}
print (nonRepeat(inputString))

在上面的例子中,它会打印出“Q”。

1
func firstNonRepeatedCharacter(input: String) -> Character?{
    var characterCount : [Character : Int] = [:]
    var uniqueCharacter: Character?

    for character in input{
        if let count = characterCount[character]{
            characterCount[character] = count + 1
            if(uniqueCharacter == character)
            {
                uniqueCharacter = nil
            }
        }
        else{
            characterCount[character] = 1
            if(uniqueCharacter == nil){
                uniqueCharacter = character
            }
        }
    }
    return uniqueCharacter
}

不需要额外的循环来从characterCount字典中查找字符。

0

这是我发现的检测第一个不重复字符的方法。它会去除空格和标点符号,以找到实际上不重复的字母或数字。

extension String {

func removeNonAlphaNumChars() -> String {
    let charSet = NSCharacterSet.alphanumericCharacterSet().invertedSet

    return self
        .componentsSeparatedByCharactersInSet(charSet)
        .joinWithSeparator("")
}

var firstNonRepeatedCharacter: Character? {
    let alphaNumString = self.removeNonAlphaNumChars()

    let characters = alphaNumString.characters
    let count = characters.count
    guard count > 0 else { return nil }

    // Find unique chars
    var dict: [Character: Int?] = [:]
    for (index, char) in characters.enumerate() {
        if dict[char] != nil {
            dict[char] = (nil as Int?)
        }
        else {
            dict[char] = index
        }
    }

    return dict.filter { $0.1 != nil }.sort { $0.1 < $1.1 }.first?.0
}
}

0

OrderedDictionary 让所有的 Sequence 都可以轻松实现这一点,而不仅仅是 String

import struct OrderedCollections.OrderedDictionary

extension Sequence where Element: Hashable {
  var firstUniqueElement: Element? {
    OrderedDictionary(zip(self, true)) { _, _  in false }
      .first(where: \.value)?
      .key
  }
}

/// `zip` a sequence with a single value, instead of another sequence.
public func zip<Sequence: Swift.Sequence, Constant>(
  _ sequence: Sequence, _ constant: Constant
) -> LazyMapSequence<
  LazySequence<Sequence>.Elements,
  (LazySequence<Sequence>.Element, Constant)
> {
 sequence.lazy.map { ($0, constant) }
}

0

我们可以迭代一次并将字母计数保存在一个字典中。 然后,再次迭代,并返回第一个只出现一次的字母(如果没有找到非重复字母,则返回“_”):

func firstNotRepeatingCharacter(s: String) -> Character {
    var letterCounts: [String: Int] = [:]
    var result: Character = "_"

    for letter in s {
        if let currentLetterCount = letterCounts[String(letter)] {
            letterCounts[String(letter)] = currentLetterCount + 1
        } else {
            letterCounts[String(letter)] = 1
        }
    }

    for letter in s {
        if letterCounts[String(letter)] == 1 {
            result = letter
            break
        }
    }

    return result
}

0

我完全想知道为什么被采纳的答案被认为是正确的。他们正在使用

.first

字典的方法根据文档会返回字典中的随机元素而不是第一个元素,因为Swift中的字典不像数组那样有序。 查看图像以查看字典作为无序集合

请查找下面的实现,它可以正常工作

func firstNonRepeatingLetter(_ str: String)  -> String{
   var characterDict = [String : Int]()

   for character in str{
       let lower = character.lowercased()
       if let count = characterDict[lower]{
         characterDict[lower] = count + 1
       }else{
        characterDict[lower] = 1
       }
   }

   let filtered = characterDict.filter { $0.value == 1}
   for character in str{
       let lower = character.lowercased()
       if let _ = filtered[lower]{
        return lower
       }
   }

   return ""
}


firstNonRepeatingLetter("moonmen") would return "e". 

-2
import Foundation
import Glibc
var str:String = "aacbbcee"//your input string
var temp:String = ""
var dict:[Character:Int] = [:]

for char in str{
    if let count = dict[char]{
        dict[char] = count+1//storing values in dict and incrmenting counts o key
    }
    else{
        dict[char] = 0
    }
}
var arr:[Character] = []
for (key, value) in dict{
    if value == 0{
        arr.append(key)//filtering out, take characters which has value>0
    }  //int(arr)
}//print(arr.count)
if arr.count != 0{
outer:for char in str{//outer is labeling the loop
    for i in arr{
        if i == char{
        print(i,"is first")//matching char with array elements if found break
        break outer
        }
        else{
            continue
        }
    }
}
}
else{
print("not found")
}

-2
func firstNonRepeatedChar(string: String) -> Character {
var arr: [Character] = []
var dict: [Character : Int] = [:]

for character in string.description {
    arr.append(character)
}

for character in arr {
    dict[character] = (dict[character] ?? 0) + 1
}
let nonRepeatedArray = arr.filter { char in
    if dict[char] == 1 {return true}
    return false
}
let firstNonRepeatedChar = nonRepeatedArray.first
return firstNonRepeatedChar! 
}
print(firstNonRepeatedChar(string: "strinstrig"))

-2
func getFirstUniqueChar(string:String)->Character?{
var counts: [String: Int] = [:]
for character in string {
    let charString = "\(character)"
    counts[charString] = (counts[charString] ?? 0) + 1
}
let firstNonRepeatingCharacter = string.first {counts["\($0)"] == 1}
return firstNonRepeatingCharacter
}

print(getFirstUniqueChar(string: string))

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