I am trying to change every duplicate in an array to the same string but with a number of this element in a row at the end. For example change ["text", "word", "text", "text"]
into ["text1", "word", "text2", "text3"]
.
Here are my ideas but they still don't work.
struct Test: View {
@State var array = ["text", "słowo", "text", "text", "siema", "elo", "siema"]
@State var test = [String : [Int]]()
var body: some View {
VStack{
ForEach(array, id:\.self) { i in
Text(i)
}
}.onAppear {
for (index,dateString) in array.enumerated() {
if(test[dateString] == nil){
test[dateString] = [index]
}else{
test[dateString]?.append(index)
}
}
test = test.filter { key, value in
value.count > 1
}
print(test)
var num = 1
for i in array.indices {
if test.keys.contains(array[i]) {
array[i] = array[i] "\(num)"
num = 1
}
}
print(array)
}
}
}
Please help!!!
CodePudding user response:
This is a straight Swift problem, not SwiftUI. Don't confuse the issue by trying to do that in your View code. This is pretty simple Swift to write:
let array = ["one", "even", "three", "even", "five", "even"]
func replaceInstances(of aString: String, with newString: String, inStringArray stringArray: [String]) -> [String] {
var output = [String]()
var itemCount = 0
for item in stringArray {
if item == aString {
itemCount = 1
output.append("\(newString)\(itemCount)")
} else {
output.append(item)
}
}
return output
}
print(replaceInstances(of: "even", with: "newString", inStringArray: array))
That outputs
["one", "newString1", "three", "newString2", "five", "newString3"]
Or
outputs:
["text1", "słowo", "text2", "text3", "siema", "elo", "siema"]
CodePudding user response:
Let's use one of Swift's awesome superpowers, extensions to the rescue!
Here we teach Swift's array of String a trick to de-duplicate its contents whilst maintaining the order of the elements.
extension Array where Element == String {
var deduplicated : Self {
var occurrences = [String : Int]()
return self.map { item in
guard let count = occurrences[item]
else {
occurrences[item] = 1 // first encounter
return item // unmodified
}
occurrences[item] = count 1
return "\( item )\( count )"
}
}
}
A quick test...
var array = ["text", "słowo", "text", "text", "siema", "elo", "siema"]
print(array.deduplicated)
// prints: ["text", "słowo", "text1", "text2", "siema", "elo", "siema1"]
The above extension can be hidden away in a sub-folder in your project called "Exntesions" as usual in a file called "Array.swift" as usual.
Now in your view you just need to make this one small change
ForEach(array.deduplicated, id:\.self) { i in
Text(i)
}