如何将词典拆分为另一个词典

时间:2018-01-12 10:16:27

标签: swift dictionary filter

考虑这个词典:

var dict = ["Steve": 17,
             "Marc": 38,
             "Xavier": 21,
             "Rolf": 45,
             "Peter": 67,
             "Nassim" : 87,
             "Raj": 266,
             "Paul": 220,
             "Bill": 392]

我需要创建一个Category对象的3个新实例:

class Category {
    var name = ""
    var note = 0
}

用var dict创建这个对象的3个新实例(即:junior,intermediate,senior)。

假设我已经知道前三个是初级,后三个是中级,后三个是高级。

谢谢,

3 个答案:

答案 0 :(得分:0)

通常,Dictionary不是有序的,所以你不能像在Array上那样迭代它。但你可以这样做:

    let array = [("Steve", 17),
                 ("Marc", 38),
                 ("Xavier", 21),
                 ("Rolf", 45),
                 ("Peter", 67),
                 ("Nassim", 87),
                 ("Raj", 266),
                 ("Paul", 220),
                 ("Bill", 392)]
    var dicts = [[String: Int]]()

    for _ in 0..<3 {
        dicts.append([String: Int]())
    }

    for i in 0..<array.count {
        dicts[i % 3][array[i].0] = array[i].1
    }

答案 1 :(得分:0)

如果您不打算更改输入数据(作业?),这可能就是您想要的:

import Foundation

var data = ["Steve": 17,
             "Marc": 38,
             "Xavier": 21,
             "Rolf": 45,
             "Peter": 67,
             "Nassim" : 87,
             "Raj": 266,
             "Paul": 220,
             "Bill": 392]


enum Seniority { case senior, junior, intermediate }

struct Worker {
    let name: String
    let note: Int
}

struct Category {
    let seniority: Seniority
    let staff: [Worker]
}

/* the partition is fixed, but at least sort by score to get it */
let all = data.sorted { (a, b) -> Bool in
    return a.value < b.value
}

/* let's use some weird variable names to note the absurd of a hardcoded partition */
let _1_3 = all.prefix(3)
let _4_6 = all.suffix(from: 3).prefix(3)
let _7_9 = all.suffix(3)

let junior = Category(seniority: .junior, staff: _1_3.map { Worker(name: $0.key, note: $0.value) })
let intermediate = Category(seniority: .intermediate, staff: _4_6.map { Worker(name: $0.key, note: $0.value) })
let senior = Category(seniority: .senior, staff: _7_9.map { Worker(name: $0.key, note: $0.value) })

让我们检查一下结果类别:

print(junior.staff.map { "\($0.name) -> \($0.note)" })
// ["Steve -> 17", "Xavier -> 21", "Marc -> 38"]
print(intermediate.staff.map { "\($0.name) -> \($0.note)" })
// ["Rolf -> 45", "Peter -> 67", "Nassim -> 87"]
print(senior.staff.map { "\($0.name) -> \($0.note)" })
// ["Paul -> 220", "Raj -> 266", "Bill -> 392"]

原始答案:

如果dict(我将其重命名为staff)中的数字是某种得分:

import Foundation

var staff = ["Steve": 17,
            "Marc": 38,
            "Xavier": 21,
            "Rolf": 45,
            "Peter": 67,
            "Nassim" : 87,
            "Raj": 266,
            "Paul": 220,
            "Bill": 392]

让我们在它们上定义一个分区:

let categories: [String:Any] = [
    "junior" : (0...19),
    "intermediate": (20..<100),
    "senior": (100...)
]

另外还有一个函数可以根据该分区返回给定分数的资历名称:

func seniority(score: Int) -> String {
    for category in categories {
        if let range = category.value as? CountableRange<Int> {
            if range.contains(score) {
                return category.key
            }
        }
        else if let range = category.value as? CountableClosedRange<Int> {
            if range.contains(score) {
                return category.key
            }
        }
        else if let range = category.value as? CountablePartialRangeFrom<Int> {
            if range.contains(score) {
                return category.key
            }
        }
    }
    fatalError("Defined ranges should cover all possible scores")
}

assert(seniority(score: staff["Steve"]!) == "junior")
assert(seniority(score: staff["Xavier"]!) == "intermediate")
assert(seniority(score: staff["Paul"]!) == "senior")

最后使用分区和定义的函数将原始staff字典拆分为“n”个新词典:

var newStaff = Dictionary(uniqueKeysWithValues: zip(categories.keys, 
                          repeatElement([String:Int](), count: categories.count)))
for (name, score) in staff {
    let category = seniority(score: score)
    newStaff[category]![name] = score
}

print(newStaff)

我得到了:

["intermediate": ["Nassim": 87, "Marc": 38, "Peter": 67, "Rolf": 45, "Xavier": 21], 
 "senior": ["Bill": 392, "Paul": 220, "Raj": 266], 
 "junior": ["Steve": 17]
]

您可以轻松地根据您的确切需求进行调整。

答案 2 :(得分:0)

我可能会定义一个这样的Worker类:​​

enum Seniority {
    case junior, intermediate, senior
}

struct Worker {
    var name: String
    var score: Int
    var seniority: Seniority
}

然后你可以将字典映射到一个工人数组(请注意,你必须使用这些名称而不能使用自Swift中dictionaries have no order以来的订单):

var workers = [Worker]()
for name in dict.keys {
    switch name {
    case "Steve", "Marc", "Xavier": workers += [Worker(name: name, score: dict[name]!, seniority: .junior)]
    case "Rolf", "Peter", "Nassim": workers += [Worker(name: name, score: dict[name]!, seniority: .intermediate)]
    default: workers += [Worker(name: name, score: dict[name]!, seniority: .senior)]
    }
}

有了它,你可以例如检索一个只有高级工作者的数组:

let seniors = workers.filter { $0.seniority == .senior }