简体   繁体   中英

NSFetchRequest: Return dictionary with nested arrays of dictionaries

Entity: Name, Category, Date, Value

The resulting dictionary of my query should be:

{
  Date1: [ 
            {
              Category1, 
              TotalValueOfCategory1InDate1
            }, 
            {
              Category2, 
              TotalValueOfCategory2InDate1
            }, 
            ... 
         ]
  Date2: [ 
            {
              Category1, 
              TotalValueOfCategory1InDate2
            }, 
            {
               Category2, 
               TotalValueOfCategory2InDate2
            }, 
            ... 
          ]
  ...
}

I tried this query:

let expr = NSExpressionDescription()
    expr.name = "total"
    expr.expression = NSExpression(format: "@sum.amount")
    expr.expressionResultType = .doubleAttributeType

    let expressions: [AnyObject] = ["category" as AnyObject, expr]
    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "EntityName")
    request.resultType = .dictionaryResultType
    request.propertiesToGroupBy = ["date", "category"]
    request.propertiesToFetch = expressions

    let res = getDictionaryFromRequest(request: request)

but the result is (obviously):

[["total": val, "date": date1, "category": category1], ["total": val, "date": date1, "category": category2], ["total": val, "date": date2, "category": category1], ["total": val, "date": date2, "category": category2], ...]

To work with this data structure I should do nested loops for each date go to recover the values of the other categories with the same date ...

I don't see any way to solve this with a different expression since this is how group by works so unless someone else who might understand NSExpressionDescription better has a solutuion here is a "fix" for the current result returned.

var dict: [String: [[String: Any]]] = [:]
for item in res {
    if let date = item["date"] as? String, 
       let category = item["category"] as? String, 
       let total = item["total"] as? Int {
        let newItem: [String: Any] = ["category":  category, "total": total]
        if dict.contains(where: { $0.key == date }) {
            dict[date]?.append(newItem)
        } else {
            dict[date] = [newItem]
        }
    }
}

PS I was lazy when testing this so both my date and category items were strings DS

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