简体   繁体   中英

How do I sort an array of dictionary according to an array contents in Swift

I have an array of dictionary. I need to sort that array. The sorting shouldnt be like ascending or descending but it should be based on an another array contents. EX: Lets say I have an array nammed array_unsorted and that array contains a lot of dictionary objects like d1, d2, d3, d4 etc. Each of the dictionary object has a key called key1 and each dictionary object has different value for that key such as Kammy , Maddy , Jessy . Lets say I have anohter sorted array which Maddy , Kammy , Jessy . Now the dictionary should be sorted in a way that the first element should the dictionary object in which the value for key1 should be Maddy`.

I cannot use SortDescriptor, because this will sort as an ascending or descending order based on the key passed to it.

I have tried my solution but I am ended up using so many nested loops. I feel like the solution I made so so pathetic that I dont even want to post the code here.

Any help would be so much appreciated.

EDIT: There can be multiple sorting arrays but as of now I am considering only one sorting array and then I can write the code for multiple sorting arrays.

How about this:

Create a new, empty dictionary with a String key, and a value of type Dictionary. Call it sourceItemsDict .

Loop through the dictionaries in your source array, and add each entry to your new dictionary, using your sort key as the dictionary key, and put the array entry as the value.

Create a new, empty array of dictionaries for your sorted results. call it sortedArray .

Now loop through your array that has the desired order in it. Fetch the item with that key from sourceItemsDict and append it to the end of sortedArray .

That should do it, and it should perform in O(n) time.

Try this:

func sort<T: Equatable>(arrayOfDict arr: [[String: T]], by key: String, order: [T]) -> [[String: T]] {
    return arr.sorted {
        guard let value0 = $0[key], let value1 = $1[key] else {
            return false
        }
        guard let index0 = order.index(of: value0), let index1 = order.index(of: value1) else {
            return false
        }

        return index0 < index1
    }
}

let array_unsorted = [
    ["name": "Kammy", "city": "New York"],
    ["name": "Maddy", "city": "Cupertino"],
    ["name": "Jessy", "city": "Mountain View"]
]
let sortedByName = sort(arrayOfDict: array_unsorted, by: "name", order: ["Maddy", "Kammy", "Jessy"])
let sortedByCity = sort(arrayOfDict: array_unsorted, by: "city", order: ["Cupertino", "Mountain View", "New York"])

print(sortedByName)
print(sortedByCity)

Your question leaves a couple of unresolved scenarios:

1: What if the key is missing from a dictionary?

let array_unsorted = [
    ["name": "Kammy", "city": "New York"],
    ["city": "Las Vegas"],
    ["name": "Maddy", "city": "Cupertino"],
    ["name": "Jessy", "city": "Mountain View"]
]

let sortedByName = sort(arrayOfDict: array_unsorted, by: "name", order: ["Maddy", "Kammy", "Jessy"])

Should Las Vegas appear at the beginning or end of the sorted array?

2: What if you don't specify an order for a value?

let array_unsorted = [
    ["name": "Amy"],
    ["name": "Kammy", "city": "New York"],
    ["name": "Maddy", "city": "Cupertino"],
    ["name": "Jessy", "city": "Mountain View"]
]

let sortedByName = sort(arrayOfDict: array_unsorted, by: "name", order: ["Maddy", "Kammy", "Jessy"])

Now where should Amy be placed?

Check out this example:

let dic1 = ["name" : "a"]
let dic2 = ["name" : "b"]
let dic3 = ["name" : "c"]
let dic4 = ["name" : "d"]
let dic5 = ["name" : "e"]


let unsorted_array = [dic2,dic5,dic1,dic4,dic3]

func sortArrayByName(_ array:[[String:String]])->[[String:String]]{
    var sortedArray:[[String:String]] = [[String:String]]()
    var sortingOrder:[String] = [String]()
    for eachDic in array{
        if let name = eachDic["name"]{
            sortingOrder.append(name)
            sortingOrder.sort() // sorting logic here

            if sortedArray.isEmpty{
                sortedArray.append(eachDic)
            } else {
                let index = sortingOrder.index(of: name)!
                sortedArray.insert(eachDic, at: index)
            }
        }
    }

    return sortedArray
}

let sorted_array = sortArrayByName(unsorted_array)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM