简体   繁体   English

如何在Swift中将字典值数组打印成漂亮的字符串

[英]How to print an array of dictionary values into a nice string in Swift

I have an array of routine objects thats are defined as: 我有一组routine对象,它们的定义为:

struct Routine {
    let routineName: String
    let routineExercisesAndSets: [String: Int]
}

let routines: [Routine] = {
    let firstRoutine = Routine(routineName: "Legs", routineExercisesAndSets: ["Squats":4,"Lunges":4,"Calf Raises":4])

    let secondRoutine = Routine(routineName: "Chest", routineExercisesAndSets: ["Bench Press":4,"Press Ups":4,"Flyes":4,"Inclined Bench Press":4])

    let thirdRoutine = Routine(routineName: "Arms", routineExercisesAndSets: ["Bicep Curls":4,"Hammer Curls":4,"Preacher Curls":4,"Tricep Extension":4,"Tricep Dips":4])

    return [firstRoutine, secondRoutine, thirdRoutine]
}()

I am trying to return them routineExercisesAndSets array into a UITableViewCell as detail text and when using the array.description function I get this result in the tableView 我正在尝试将它们的routineExercisesAndSets数组作为详细文本返回到UITableViewCell中,当使用array.description函数时,我在tableView中得到此结果

这个结果在tableView中

My question is, how could I iterate through the routine objects and print out a 'pretty' formatted string that looks something like: 我的问题是,我该如何遍历例程对象并打印出一个“漂亮的”格式的字符串,看起来像这样:

"Calf Raises x 4, Squats x 4, Lunges x 4..."

I can print out the individual key, value pairs on new lines using this code: 我可以使用以下代码在新行上打印出各个键,值对:

for i in routines{
    for (key, value) in (i.routineExercisesAndSets)! {
        print("\(key) x \(String(value))")
    }
}

which produces: 产生:

Calf Raises x 4 Squats x 4 Lunges x 4 Bench Press x 4 Press Ups x 4 Flyes x 4 Inclined Bench Press x 4 Tricep Extension x 4 Tricep Dips x 4 Preacher Curls x 4 Hammer Curls x 4 Bicep Curls x 4

but I want to group them by their parent object so the exercises for a routine display on the same line so it looks like the example "Calf Raises x 4, Squats x 4, Lunges x 4..." . 但是我想按它们的父对象对它们进行分组,以便将例行练习显示在同一行上,因此看起来像示例"Calf Raises x 4, Squats x 4, Lunges x 4..."

You could make of a chained map and joined operation to construct a single String describing the exercise dictionary for a given exercise. 您可以通过链接mapjoined操作来构造单个String描述给定练习的练习字典。 Eg 例如

for routine in routines {
    print("Routine:", routine.routineName)
    print("--------------")
    print(routine.routineExercisesAndSets
        .map { $0 + " x \($1)" }
        .joined(separator: ", "))
    print()
}
/* Routine: Legs
   --------------
   Calf Raises x 4, Squats x 4, Lunges x 4

   Routine: Chest
   --------------
   Bench Press x 4, Press Ups x 4, Flyes x 4, Inclined Bench Press x 4

   Routine: Arms
   --------------
   Tricep Extension x 4, Tricep Dips x 4, Preacher Curls x 4, Hammer Curls x 4, Bicep Curls x 4 

                   */

Furthermore, instead of explicitly performing these "presentation" conversions upon each use, you could implement them as the return of the computed description property of Routine , as a part of letting Routine conform to CustomStringConvertible : 此外,您可以将它们实现为Routine的计算description属性的返回,而不是在每次使用时显式执行这些“表示”转换,这是使Routine符合CustomStringConvertible

extension Routine: CustomStringConvertible {
    var description: String {
        return routineName + ":\n" + routineExercisesAndSets
            .map { $0 + " x \($1)" }
            .joined(separator: ", ")
    }
}

for routine in routines {
    print(routine) /* uses Routine:s implementation of 'CustomStringConvertible',
                      the computed property 'description`, specifically           */
    print()
}
/* Legs:
   Calf Raises x 4, Squats x 4, Lunges x 4

   Chest:
   Bench Press x 4, Press Ups x 4, Flyes x 4, Inclined Bench Press x 4

   Arms:
   Tricep Extension x 4, Tricep Dips x 4, Preacher Curls x 4, Hammer Curls x 4, Bicep Curls x 4

                   */

Given your comment below, it seems as if the properties routineName and routineExercisesAndSets of Routine are optionals. 鉴于您在下面的评论,似乎Routine的属性routineNameRoutine routineExercisesAndSets是可选的。 If this is the case, you naturally need to handle unwrapping them prior to accessing their (possibly existing) values. 如果是这种情况,您自然需要在访问它们(可能存在的)值之前处理它们的展开。 Eg, returning an empty description if any of the two properties is nil , and otherwise, the combined routine name and details description (as done in the non-optional examples above): 例如,如果两个属性中的任何一个为nil ,则返回一个空的description ,否则返回组合的例程名称和详细信息描述(如上面的非可选示例所述):

struct Routine {
    let routineName: String?
    let routineExercisesAndSets: [String: Int]?
}

extension Routine: CustomStringConvertible {
    var description: String {
        guard let name = routineName, let details = routineExercisesAndSets else { return "" }
        return name + ":\n" + details.map { $0 + " x \($1)" }.joined(separator: ", ")
    }
}

First of all let's conform Routine to CustomStringConvertible 首先,让Routine符合CustomStringConvertible

extension Routine: CustomStringConvertible {
    var description: String {
        return routineExercisesAndSets.map { $0 + " x " + $1.description }.joined(separator: ", ")
    }
}

Now you can easily write 现在您可以轻松编写

routines.forEach { print($0) }

Result 结果

Calf Raises x 4, Squats x 4, Lunges x 4
Bench Press x 4, Press Ups x 4, Flyes x 4, Inclined Bench Press x 4
Tricep Extension x 4, Tricep Dips x 4, Preacher Curls x 4, Hammer Curls x 4, Bicep Curls x 4

Or given a UITableViewCell ... 或给定一个UITableViewCell ...

let cell: UITableViewCell = ...
let routine: Routine = ...
cell.detailTextLabel?.text = routine.description

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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