【问题标题】:How to transform array to 2d array using reduce(into:_:)?如何使用 reduce(into:_:) 将数组转换为二维数组?
【发布时间】:2019-04-08 22:00:39
【问题描述】:

我有一个自定义模型数组:

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

作为:

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,结果应该是:

[
    [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")]
]

外部二维数组中的第一个数组包含1 日的事件,第二个包含2 日的事件。

有没有办法使用reduce(into:_:)方法得到上述结果?


尽管想使用reduce(into:_:) 来实现,但我能够通过实现来实现:

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

【问题讨论】:

  • 为什么是reduce(into:_:)?像Array(Dictionary(grouping: array, by: { $0.day }).values) 这样的东西应该可以解决问题。
  • 是什么让您认为reduce(into:-:) 适合该任务?我的意思是,这真的是一个要求吗?
  • 你无法使用reduce(into:_:)Reduce 将数组的所有元素缩减为单个值。 D V 使用dictionary(grouping:) 的答案应该可以。
  • @DuncanC 我不同意

标签: arrays swift reduce


【解决方案1】:

要以更简单的方式做到这一点,您可以使用@MartinR 的评论:

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

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

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

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

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

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

【讨论】:

    【解决方案2】:

    如果你还想要reduce(into:):

    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]]
            }
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用字典分组功能来实现您的要求:

      // 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)")
      }
      

      【讨论】:

        猜你喜欢
        • 2011-07-05
        • 2019-07-09
        • 2015-07-16
        • 1970-01-01
        • 1970-01-01
        • 2016-02-18
        • 2018-02-19
        相关资源
        最近更新 更多