关于swift:如何使用reduce(into:_ :)将数组转换为2d数组?

How to transform array to 2d array using reduce(into:_:)?

我有一组自定义模型:

1
2
3
4
struct Event {
    var day: Int // let's assume its Int for now
    var title: String
}

为:

1
2
3
4
let array = [Event(day: 1, title:"Pizza Party!"),
             Event(day: 1, title:"Another Pizza Party"),
             Event(day: 2, title:"Cinema - Moive 01"),
             Event(day: 2, title:"Cinema - Moive 02")]

我想将array转换为二维数组,每个数组应包含具有同一天的事件;根据array,结果应为:

1
2
3
4
[
    [Event(day: 1, title:"Pizza Party!"), Event(day: 1, title:"Another Pizza Party")]
    [Event(day: 2, title:"Cinema - Moive 01"), Event(day: 2, title:"Cinema - Moive 02")]
]

第一个数组(在外部2d数组中)包含第1天的事件,第二个数组包含第2天的事件。

是否可以使用reduce(into:_:)方法获得以上结果?

尽管想使用reduce(into:_:)做到这一点,但我仍然可以通过实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func transfrom(_ models: [Event]) -> [[Event]] {
    let uniqueDates = Set(array.map { $0.day }).sorted()
    var twoDArray = [[Event]]()

    for date in uniqueDates {
        var array = [Event]()
        for model in models {
            if date == model.day {
                array.append(model)
            }
        }

        twoDArray.append(array)
    }

    return twoDArray
}

let transfomredArray = transfrom(array) // wanted result


您可以使用Dictionary的分组功能来满足您的要求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// This dictionary will have all your events grouped based on the day it belongs to.
let dict = Dictionary(grouping: array) { (element) -> Int in
    return element.day
}

// If you need a sorted list of events based on the day.
let groupedItems = dict.sorted {
    return $0.key < $1.key
}

// groupedItems would now have all the data, grouped and ready to be used.
for day in groupedItems {
    print("\\(day.key): \\(day.value.count)")
}

要以更简单的方式进行操作,可以使用@MartinR的注释:

1
let resultArray = Dictionary(grouping: array, by: { $0.day }).values

但是您可能要对它执行一些额外的操作,可以说是排序。然后,您可以使用以下方法:

  • 根据day参数对数据进行分组。结果将是[Int: [Event]]

    1
    let grouped = Dictionary(grouping: array, by: { $0.day })
  • 根据键对分组的数据进行排序。结果将是[Int: [Event]]

    1
    let sorted = grouped.sorted(by: { $0.key < $1.key })
  • 您可以使用reduce获得所需格式的输出,请注意,只需应用reduce即可使数组变平,因此请使用{ $0 + [$1.value] }

    1
    let resultArray: [[Event]] = sorted.reduce([]) { $0 + [$1.value] }

  • 如果您仍然想要reduce(into:)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    let result: [[Event]] = array.sorted { $0.day < $1.day }
        .reduce(into: [[Event]]())
        { tempo, event in
            if let lastArray = tempo.last {
                if lastArray.first?.day == event.day {
                    let head: [[Event]] = Array(tempo.dropLast())
                    let tail: [[Event]] = [lastArray + [event]]
                    tempo = head + tail
                }
                else {
                    tempo.append([event])
                }
            } else {
                tempo = [[event]]
            }
    }