3

I have a bunch or arrays in a data struct that I am combining into one array and deleting any duplicates. Is it possible to move an item to the top of the array so it is first in the list? I want All to appear at the top of the list but it is currently sitting in the second position because of Agriculture.

Here are some of the arrays in the data struct:

let productData: [ProductModel] = [
    ProductModel(application: ["All", "Clean Chemistry", "Food", "Agriculture", "Polymers"]),
    ProductModel(application: ["All", "Food", "Agriculture", "Gin", "Polymers"]),
    ProductModel(application: ["All", "Metals", "Polymers"]),
]

Here is where I am organising the array and presenting it in a HStack:

struct ProductList: View {
    var applicationsArray = Array(Set(productData.flatMap(\.application))).sorted()
    var body: some View {
        ScrollView(.horizontal){
            HStack{
                ForEach(applicationsArray, id: \.self) { item in
                    Button(action: {
                        // SELECT ITEM
                    }) {
                        VStack(alignment: .center){
                            Image(item)
                            Text(item)
                        }
                    }
                }
            }
        }
    }
}

2 Answers 2

3

Use the closure provided to sorted(by:) to sort "All" to the front of the list:

var applicationsArray = Set(productData.flatMap(\.application))
    .sorted { (a: String, b: String) -> Bool in
        a == "All" ? true : b == "All" ? false : a < b
    }

Explanation

The closure that you provide to sorted(by:) is called repeatedly by sorted and it takes two elements at a time and decides if the first element should come before the second element. Since you want "All" to appear at the start of the list, then if the closure receives "All" as the first element, it should return true because "All" comes before every other element. If the closure receives "All" as the second element, it returns false because no elements come before "All". Finally, if "All" isn't one of the elements sent to the closure, it just compares to see if the first comes before the second lexicographically using a < b.

Sign up to request clarification or add additional context in comments.

2 Comments

I get this error when trying this: The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
I fixed it by making the types of the closure explicit.
2

First, remove duplicates from your list, then filter out the item(s) you want to show at the top of your list and filter out the rest of your items except the top ones and add them together. Easy right?

var yourList = ["All", "Clean Chemistry", "Food", "Agriculture", "Polymers", "All", "Food", "Agriculture”, "Gin”, "Polymers”, "All”, "Metals”, "Polymers”]

var removeDuplicates = Array(Set(yourList)).sorted()
print(removeDuplicates)

var getAllFromTheList = removeDuplicates.filter(){$0 == "All"}
print(getAllFromTheList) // [“All”]

var removeAllFromTheList = removeDuplicates.filter(){$0 != "All"}
print(removeAllFromTheList) // [“Agriculture”, “Clean Chemistry”, “Food”, “Gin”, “Metals”, “Polymers”]

let newList = getAllFromTheList + removeAllFromTheList
print(newList) // [“All”, “Agriculture”, “Clean Chemistry”, “Food”, “Gin”, “Metals”, “Polymers”]

2 Comments

Thanks for breaking it down, it all makes sense. I think @vacawama's answer is also great as its compact.
Yeah, I like his answer too, but it’s hard to understand for beginners. That’s why I explained it step by step :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.