Tio
Tio

Reputation: 1036

How to check for duplicate elements in strings array

I'm currently developing an application using SwiftUI.

If I run the code below, the display result will be A, But I want to make it the display result B.

What kind of code can this be achieved?

enter image description here


Here is the code:

struct TestView:View {

    let fruits = ["apple","apple","apple","orange","orange","banana"]

    @State var tmpFruits = [""]

    var body: some View{

        List(fruits, id: \.self){fruit in
            if tmpFruits.contains(fruit) == false{

                Button(action: {
                }, label: {
                    Text(fruit)
                })
                .onAppear(){
                    tmpFruits.append(fruit)
                }
            }
        }
    }
}

Swift 5.0

SwiftUI 2.0

Upvotes: 0

Views: 609

Answers (3)

George
George

Reputation: 30391

You need to have a List with unique and constant IDs. Currently, the ID is the string for each element in fruits. The problem with that is since there are repeated items, you are violating the unique ID rule.

A way to solve this is filtering fruits first, hence unique IDs. It also greatly simplifies the view code.

This uses Unique from apple/swift-algorithms for .uniqued(). Remember to import Algorithms.

Code:

import Algorithms

struct TestView: View {
    private let fruits = ["apple", "apple", "apple", "orange", "orange", "banana"]

    var body: some View {
        List(Array(fruits.uniqued()), id: \.self) { fruit in
            Button(fruit) {
                print("action")
            }
        }
    }
}

Upvotes: 2

Alexander
Alexander

Reputation: 63271

Ideally, you should use the official swift-algorithms package to gain access to a uniqued() function on sequences, which will do exactly what you're looking for.

If you're not using SPM or don't want to pull in that dependancy (though I really do encourage it, it's a first party Apple library, it's open source, and has really great stuff!), you can use a hand-rolled extension, like the community has been doing for years. Something like this would work for your purposes

public extension Sequence where Element: Hashable {

    /// Return the sequence with all duplicates removed.
    ///
    /// i.e. `[ 1, 2, 3, 1, 2 ].uniqued() == [ 1, 2, 3 ]`
    ///
    /// - note: Taken from stackoverflow.com/a/46354989/3141234, as 
    ///         per @Alexander's comment.
    func uniqued() -> [Element] {
        var seen = Set<Element>()
        return self.filter { seen.insert($0).inserted }
    }
}

Once that's in place, this is as simple as:

struct TestView: View {
    private let fruits = ["apple", "apple", "apple", "orange", "orange", "banana"]

    var body: some View {
        List(fruits.uniqued(), id: \.self) { fruit in
            Button(fruit) {
                print("action")
            }
        }
    }
}

Upvotes: 1

gabriele cusimano
gabriele cusimano

Reputation: 1

Try with this

List {
    ForEach(fruits, id: \.self) { fruit in
        if !tmpFruits.contains(fruit) {
            Button(action: {

            }, label: {
                Text(fruit)
            })
            .onAppear() {
                tmpFruits.append(fruit)
                print(tmpFruits)
            }
        }
    }
}

Upvotes: 0

Related Questions