【问题标题】:How to organize array of dictionaries based on the value of a key within them?如何根据其中的键值组织字典数组?
【发布时间】:2020-03-27 23:01:09
【问题描述】:

我有一个信息数组存储如下:

(
            {
        actual = "<null>";
        code = "AUTO.US";
        date = "2019-12-31";
        difference = "<null>";
        estimate = "-0.12";
        percent = "<null>";
        "report_date" = "2020-03-27";
    },
            {
        actual = "<null>";
        code = "APTX.US";
        date = "2019-12-31";
        difference = "<null>";
        estimate = "-0.5600000000000001";
        percent = "<null>";
        "report_date" = "2020-03-30";
    },
{

        actual = "<null>";
        code = "BLAH.US";
        date = "2019-12-31";
        difference = "<null>";
        estimate = "-0.5600000000000001";
        percent = "<null>";
        "report_date" = "2020-03-30";
    }
);

我想创建一个字典数组,每个report_date 的键包含与该日期匹配的上述字典数组。这就是我想要完成的:

(
        {
        "2020-03-27" =         (
                        {
                actual = "<null>";
                code = "AUTO.US";
                date = "2019-12-31";
                difference = "<null>";
                estimate = "-0.12";
                percent = "<null>";
                "report_date" = "2020-03-27";
            }
        );
    },
        {
        "2020-03-30" =         (
                        {
                actual = "<null>";
                code = "APTX.US";
                date = "2019-12-31";
                difference = "<null>";
                estimate = "-0.5600000000000001";
                percent = "<null>";
                "report_date" = "2020-03-30";
            },
        {

        actual = "<null>";
        code = "BLAH.US";
        date = "2019-12-31";
        difference = "<null>";
        estimate = "-0.5600000000000001";
        percent = "<null>";
        "report_date" = "2020-03-30";
    }
        );
    }
)

为澄清起见,我想得到一个数组,其中包含日期为日期的字典,其对象包含具有与该键匹配的 report_date 的原始字典数组。因此,键下的数组中可能有多个收入字典。

感谢您对此提供的任何帮助!

【问题讨论】:

    标签: ios arrays swift dictionary


    【解决方案1】:

    你不应该在 Swift 中使用 NSDictionaryNSArray,除非在极少数情况下。你应该使用 Swift 数组和字典。如果您创建了一个适当的struct 来保存您的数据而不是使用原始字典,这也会有所帮助。如果您的数据来自 JSON,那么您可以使用 Codable 非常简单地转换您的数据。

    但是,使用您所拥有的,您需要将 [String:String] 字典数组转换为 [String:String], keyed by a[String]or the rather ugly[String:[[String:String]]] 数组字典`:

    为此,只需遍历初始数组,将每个字典添加到 [String:[[String:String]]] 字典:

    func createEarningsDictionary(from earnings:[[String:String]] ) -> [String:[[String:String]]] {
        var arrayOfEarningsDicts = [String:[[String:String]]]()
    
        for earning in earnings {
            if let reportDate = earning["report_date"] {
                arrayOfEarningsDicts[reportDate, default:[[String:String]]()].append(earning)
        }
        return arrayOfEarningsDicts
    }
    

    如果您使用 Earnings 结构而不是 [String:String] 字典,您将拥有更易读的内容:

    func createEarningsDictionary(from earnings:[Earnings] ) -> [String:[Earnings]] {
        var earningsDict = [String:[Earnings]]()
    
        for earning in earnings {
            earningsDict[earning.reportDate, default:[Earnings]()].append(earning)
        }
        return earningsDict
    }
    

    【讨论】:

    • 我正在尝试您的答案,但我必须使用 String:Any,因为原始字典中有一个 NSNumber。但由于某种原因,附加在 if let 语句中的行返回 nil。为了澄清起见,我想最终得到一个数组,其中包含以日期为日期的字典,该数组将具有与该键匹配的 report_date 的原始字典的数组作为其对象。所以键下的数组中可能有不止一个收益字典。
    • 是的,我的代码就是这样做的。我使用从您的示例数据创建的字典 [String:String] 对其进行了测试,并添加了具有相同 report_date 的额外字典。您必须使用 [String:Any] 的字典所遇到的困难是为什么您应该创建一个 Earnings 结构的数组。您的数据是否来自 JSON?
    • 是的,是的。我上面表示的方式是它来自 JSON。
    • 绝对使用CodableJSONDecoder 将其转换为结构数组——这将使您的数据更易于处理并消除NSNumber
    • 好的,我会调查的。谢谢你。但是,我手动将 NSNumber 替换为它的 stringValue 来测试您的代码。它有效,但仅适用于其中一个收入词典。我只得到一个报告日期,但没有得到另一个(经过两个不同的日期)。 [“2020-03-27”:[[“report_date”:“2020-03-27”,“估计”:“-0.12”,“代码”:“AUTO.US”,“日期”:“2019-12 -31"]]]
    【解决方案2】:

    这个问题有点误导,但是:

    原始数据已经是[[String: String]] 类型的数组,而您需要的结果是[[String: [String: String]]] 类型的数组。

    按照以下代码到达那里:

    // building the original data
    var dic1: [String: String] = [:]
    dic1["actual"] = "<null>"
    dic1["code"] = "AUTO.US"
    dic1["date"] = "2019-12-31"
    dic1["difference"] = "<null>"
    dic1["estimate"] = "-0.12"
    dic1["percent"] = "<null>"
    dic1["report_date"] = "2020-03-27"
    
    var dic2: [String: String] = [:]
    dic2["actual"] = "<null>"
    dic2["code"] = "APTX.US"
    dic2["date"] = "2019-12-31"
    dic2["difference"] = "<null>"
    dic2["estimate"] = "-0.5600000000000001"
    dic2["percent"] = "<null>"
    dic2["report_date"] = "2020-03-30"
    
    // the array of the original data
    let array = [dic1, dic2]
    
    // the interesting function
    func sortThemOut() {
        var finalArray: [[String: [String: String]]] = []
        for dic in array {
            // get the `report_date` value from the original dictionary
            let reportDate = dic["report_date"] ?? "there was no value for the `report_date`"
            // create the new item that should be appended in the new array
            var newDic: [String: [String: String]] = [:]
            // set the key to the `reportDate`, and the value of that key to the original dictionary
            newDic[reportDate] = dic
            
            // append the new dictionary into the final array
            finalArray.append(newDic)
        }
        print(finalArray)
    }
    

    我仍然强烈建议您将其更改为将原始数据转换为 [String: [String: String]] 类型的字典,我相信这是您真正想要得到的:

    // the array of the original data
    let array = [dic1, dic2]
    
    func sortThemOut() {
        var finalDictionary: [String: [String: String]] = [:]
        for dic in array {
            // get the `report_date` value from the original dictionary
            let reportDate = dic["report_date"] ?? "there was no value for the `report_date`"
            // set the key to the `reportDate`, and the value of that key to the original dictionary
            finalDictionary[reportDate] = dic
        }
        print(finalDictionary)
    }
    

    你可以这样使用:

        // key will represent the `report_date`, and the value will contain the rest of the object
        for (key, value) in finalDictionary {
            print("key: " + key)
            print("value: \(value)")
            
            // OUTPUT:
            
            // key: 2020-03-27
            // value: ["report_date": "2020-03-27", "estimate": "-0.12", "code": "AUTO.US", "difference": "<null>", "date": "2019-12-31", "actual": "<null>", "percent": "<null>"]
            
            // key: 2020-03-30
            // value: ["report_date": "2020-03-30", "estimate": "-0.5600000000000001", "date": "2019-12-31", "difference": "<null>", "percent": "<null>", "actual": "<null>", "code": "APTX.US"]
        }
        
        print(finalDictionary["2020-03-27"])
        // ["report_date": "2020-03-27", "estimate": "-0.12", "code": "AUTO.US", "difference": "<null>", "date": "2019-12-31", "actual": "<null>", "percent": "<null>"]
    

    更新

    根据以下 cmets 中的说明,生成的对象将是 `[String: [[String: String]]]' 类型的字典,因此函数为:

    func sortThemOut() {
        var finalDictionary: [String: [[String: String]]] = [:]
        for dic in array {
            // get the `report_date` value from the original dictionary
            let reportDate = dic["report_date"] ?? "there was no value for the `report_date`"
            // creating an array that will hold the original objects
            // try to get the array that was previously inserted (if a previous object with same report_date was inserted before, or assign an new empty array
            var objects = finalDictionary[reportDate] ?? []
            
            // append the object into the array
            objects.append(dic)
            
            // set the key to the `reportDate`, and the value of that key to the array of original objects
            finalDictionary[reportDate] = objects
        }
    }
    

    【讨论】:

    • 感谢您的回答!为了澄清起见,我想最终得到一个数组,其中包含以日期为日期的字典,该数组将具有与该键匹配的 report_date 的原始字典的数组作为其对象。因此,键下的数组中可能有多个收入字典。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-15
    • 1970-01-01
    • 2014-12-31
    相关资源
    最近更新 更多