SriTeja Chilakamarri
SriTeja Chilakamarri

Reputation: 2703

How can I group an array with dictionaries using a Key value.

I am working with Json which has response something like this

{"Type": "ABCDEF", "user_photo": "c16a8ad9bf08f966.jpg", "time": 1540399975658}

So I converted this to below by using a custom function so that I can see the value for Today, Yesterday, last week, Last month etc.

{"Type": "ABCDEF", "user_photo": "c16a8ad9bf08f966.jpg", "time": "Today"}

Now I am trying to display this on a tableview using this structure in different section with each section showing up items of particular time.

All items in today will be in one section. All items in yesterday will be in one section so on.

I have an array of all these responses and I am trying to group them into a dictionary with each key value having the same time key. If I am able to solve this I guess using them for sections would be pretty easy

This is what I am trying to achieve.

I am stuck in this and not quite sure how I could continue on this.

1 solution I tried but failed was to have an array of Times and matching array of responses. Tried grouping Times array but it did not work.

Upvotes: 0

Views: 2625

Answers (3)

ielyamani
ielyamani

Reputation: 18591

You could define a dictionary with all the notifications:

var notifcationsDict: [String: [Notification]] = ["Today": [],
                                                  "Yesterday": [],
                                                  "Last week": [],
                                                  "Last month": [],]

Define a struct for notifications:

struct Notification: Decodable {
    let type, userPhoto, time: String

    enum CodingKeys: String, CodingKey {
        case type = "Type"
        case userPhoto = "user_photo"
        case time
    }
}

(Notice the use of coding keys to conform to the Swift way of naming properties)

Then you could decode the json and append the notification to the corresponding key in the dictionary:

let json = """
{
    "Type": "ABCDEF",
    "user_photo": "c16a8ad9bf08f966.jpg",
    "time": "Today"
}
"""

guard let jsonData = json.data(using: .utf8) else {
    fatalError("Couldn't get the json to data")
}

do {
    let notification = try JSONDecoder().decode(Notification.self, from: jsonData)
    notifcationsDict[notification.time]?.append(notification)
    print(notifcationsDict)
} catch {
    print(error)
}

Upvotes: 1

E.Coms
E.Coms

Reputation: 11539

You may use array from the original JSON string and then parse it in your own way.

Thus you have separate a grouping question apart from parsing questions.

As shown in the following code and try it in playground.

    let array = ["{\"Type\": \"ABCDEF\", \"user_photo\": \"c16a8ad9bf08f966.jpg\", \"time\": \"last week\"}", "{\"Type\": \"ABCDEF\", \"user_photo\": \"c16a8ad9bf08f966.jpg\", \"time\": \"Tomorrow\"}" , "{\"Type\": \"ABCDEF\", \"user_photo\": \"c16a8ad9bf08f966.jpg\", \"time\": \"Today\"}","{\"Type\": \"ABCDEF\", \"user_photo\": \"c16a8ad9bf08f966.jpg\", \"time\": \"Today\"}"]
    let re = try  NSRegularExpression.init(pattern: "(\\\"([^\"])*\\\")[\\s}]+$", options:  [.anchorsMatchLines ,. allowCommentsAndWhitespace])
    let dict =  Dictionary.init(grouping: array) {
            return ($0 as NSString).substring(with: re.matches(in: $0, options: [], range: NSRange.init(location: 0, length: $0.count))[0].range(at: 1))
    }
    print(dict)

The result is :

 ["\"last week \"": ["{\"Type\": \"ABCDEF\", \"user_photo\": \"c16a8ad9bf08f966.jpg\", \"time\": \"last week \"  }"], "\"Tomorrow\"": ["{\"Type\": \"ABCDEF\", \"user_photo\": \"c16a8ad9bf08f966.jpg\", \"time\": \"Tomorrow\"}"], "\"Today\"": ["{\"Type\": \"ABCDEF\", \"user_photo\": \"c16a8ad9bf08f966.jpg\", \"time\": \"Today\"}", "{\"Type\": \"ABCDEF\", \"user_photo\": \"c16a8ad9bf08f966.jpg\", \"time\": \"Today\"}"]]

Upvotes: 1

Daniil Subbotin
Daniil Subbotin

Reputation: 6718

Create an empty dictionary of type [String: [Item]].

var dict = [String: [Item]]()

Loop through all the items in the original array and make next thing. If there is not a key with the given name, create empty array and append an item, else add item in the existing array.

for item in items {
    dict[item.time, default: []].append(item)
}

Call dict["Today"] and you will get an array of items with the time = "Today".


Swift 4

Dictionary(grouping: items, by: { $0.time })

Upvotes: 2

Related Questions