Move/Reorder specific item in Array - SwiftUI

Viewed 169

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

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.

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”]
Related