Home > OS >  SwiftUI: Change string of a duplicates in array
SwiftUI: Change string of a duplicates in array

Time:08-13

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)
}
  • Related