【问题标题】:Group days of the week with same values in Swift在 Swift 中用相同的值分组一周中的几天
【发布时间】:2021-03-13 11:15:51
【问题描述】:

我有一个服务请求,其中包含一个名为“hoursArray”的数组中的商店时间表,格式如下:

"hours": [
      "00:00-23:59",
      "00:00-23:59",
      "00:00-21:59",
      "00:00-21:59",
      "00:00-22:59",
      "00:00-22:59",
      "00:00-23:59"
    ]

我在一个包含两个垂直堆栈视图的水平堆栈视图中显示此信息,一个带有一周中 7 天的标签,另一个带有那天日程安排的七个标签,我用这个函数填充这个标签:

  func getSchedule(){
        scheduleLabel1.text = hoursArray[0] as? String
        scheduleLabel2.text = hoursArray[1] as? String
        scheduleLabel3.text = hoursArray[2] as? String
        scheduleLabel4.text = hoursArray[3] as? String
        scheduleLabel5.text = hoursArray[4] as? String
        scheduleLabel6.text = hoursArray[5] as? String
        scheduleLabel7.text = hoursArray[6] as? String
        dayLabel1.text = "Monday"
        dayLabel2.text = "Tuesday"
        dayLabel3.text = "Wednesday"
        dayLabel4.text = "Thursday"
        dayLabel5.text = "Friday"
        dayLabel6.text = "Saturday"
        dayLabel7.text = "Sunday"
    }

我需要将相关日期分组以在我收到具有相同值的日期的请求响应时显示它,例如,如果星期一和星期二具有相同的值,我将在 day1Label 中显示“星期一 - 星期二”。 scheduleLabel1.text 中的文本及其时间表,我该怎么做?

【问题讨论】:

  • 这是关于如何对数据进行分组或如何处理 UI 中不同数量的标签?
  • 两者,因为我需要首先处理我的数据,然后我需要处理标签的数量和分组它们的日期名称的值

标签: arrays swift label schedule


【解决方案1】:

您可以使用以下函数来格式化

let hours = [
    "00:00-23:59",
    "00:00-23:59",
    "00:00-21:59",
    "00:00-21:59",
    "00:00-22:59",
    "00:00-22:59",
    "00:00-23:59"
]

let days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]


func format() -> [(String, String)] {
    
    var temp: [(String, String)] = []
    for i in 0..<hours.count {
        temp.append((days[i], hours[i]))
    }
    
    var result: [(String, String)] = []
    
    var index = 0
    
    var dayStart: String?
    var dayEnd: String?
    var time: String?
    
    while index < temp.count {
        
        if dayStart == nil {
            dayStart = temp[index].0
            time = temp[index].1
        }
        
        if (index != temp.count - 1) && (temp[index].1 == temp[index+1].1)  {
            dayEnd = temp[index+1].0
            index += 1
        }
        else {
            if let start = dayStart, let tm = time {
                if let end = dayEnd {
                    result.append(("\(start)-\(end)", tm))
                    dayEnd = nil
                }
                else {
                    result.append((start, tm))
                }
                dayStart = nil
                time = nil
            }
            index += 1
        }
    }
    return result
}

从中您将获得格式化的结果,然后您可以将这些作为输入传递给 TableView 或 IBOutletCollection。不建议对这些使用静态标签,因为基于组的标签数量可能会在 1-7 之间发生变化。所以还是用Tableview比较好。

【讨论】:

  • 您可以将第一个 for 循环替换为 zip 函数以组合 2 个数组。
  • @flanker 我不知道这样的功能存在。谢谢,我现在知道了
  • @JoakimDanielson 要在标签中显示,最好使用 TableView 或 IBOutletCollection 而不是 7 个标签,因为现在根据标签的分组数量可能会发生变化。
【解决方案2】:

一种方法是这样的,首先按小时范围对数据进行分组:

let hourRanges = [
    "00:00-23:59",
    "00:00-23:59",
    "00:00-21:59",
    "00:00-21:59",
    "00:00-22:59",
    "00:00-22:59",
    "00:00-23:59"
]

let weekDays = [
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
    "Sunday",
]

struct WeekDaysHourRange {
    let hourRange: String
    var weekDays: [String]
}

var daysRanges: [WeekDaysHourRange] = []

// assuming both arrays have the same length, otherwise checks are needed    
var previousWeekDayRange: WeekDaysHourRange?
for i in 0...6 {
    let hourRange = hourRanges[i]
    let weekDay = weekDays[i]
    
    if previousWeekDayRange?.hourRange == hourRange {
        daysRanges[daysRanges.count - 1].weekDays.append(weekDay)
    } else {
        let newWeekDayRange = WeekDaysHourRange(hourRange: hourRange, weekDays: [weekDay])
        previousWeekDayRange = newWeekDayRange
        daysRanges.append(newWeekDayRange)
    }
}

为了更新 UI,我将创建 UILabels 数组,以允许使用 for 循环轻松填充标签,如下所示:

let scheduleLabels: [UILabel] = [
    scheduleLabel1,
    scheduleLabel2,
    scheduleLabel3,
    scheduleLabel4,
    scheduleLabel5,
    scheduleLabel6,
    scheduleLabel7
]

let dayLabels: [UILabel] = [
    dayLabel1,
    dayLabel2,
    dayLabel3,
    dayLabel4,
    dayLabel5,
    dayLabel6,
    dayLabel7
]

daysRanges.enumerated().forEach { (i, weekDayHourRange) in
    var daysString: String
    if weekDayHourRange.weekDays.count == 1 {
        daysString = weekDayHourRange.weekDays.first!
    } else {
        daysString = "\(weekDayHourRange.weekDays.first!) - \(weekDayHourRange.weekDays.last!)"
    }
    
    dayLabels[i].text = daysString
    scheduleLabels[i].text = weekDayHourRange.hourRange
}

根据 Joakim Danielson 的评论,如果您只需要创建一次视图而不更新它,您可以即时创建视图:

daysRanges.enumerated().forEach { (i, weekDayHourRange) in
    var daysString: String
    if weekDayHourRange.weekDays.count == 1 {
        daysString = weekDayHourRange.weekDays.first!
    } else {
        daysString = "\(weekDayHourRange.weekDays.first!) - \(weekDayHourRange.weekDays.last!)"
    }

    let dayLabel = UILabel()
    dayLabel.text = daysString
    
    let scheduleLabel = UILabel()
    scheduleLabel.text = weekDayHourRange.hourRange
    
    dayLabelsStackView.addArrangedSubview(dayLabel)
    scheduleLabelsStackView.addArrangedSubview(scheduleLabel)
}

这将输出如下内容:

"Monday - Tuesday - 00:00-23:59"
"Wednesday - Thursday - 00:00-21:59"
"Friday - Saturday - 00:00-22:59"
"Sunday - 00:00-23:59"

【讨论】:

  • 这只是一个指导方针,但我会更新我的答案
【解决方案3】:

已经有一些不错的答案,但读到这里,似乎一种函数式方法非常适合处理输入。这种方法使用 zip 将两个数据集组合成一个元组数组,然后通过减少来合并它们,并通过一些模式匹配将字符串分解为所需的形状。最后,它使用 map 遍历结果数组以将合并的项目添加到堆栈视图。

let days = ["Monday",
            "Tuesday",
            "Wednesday",
            "Thursday",
            "Friday",
            "Saturday",
            "Sunday"
]

let hours = [
   "00:00-23:59",
   "00:00-23:59",
   "00:00-23:59",
   "00:00-21:59",
   "00:00-22:59",
   "00:00-22:59",
   "00:00-23:59"
]


zip(days, hours)
   .reduce([(String, String)]()){
      guard let last = $0.last else {return [$1]}
      if last.1 == $1.1 {
         var days = last.0
         if let lastDayRange = days.range(of: #"(?<=- )[A-Z,a-z]*day"#, options: .regularExpression) {
            days.replaceSubrange(lastDayRange, with: $1.0)
         } else {
            days = days + " - \($1.0)"
         }
         return $0.dropLast() + [(days, $1.1)]
      } else {
         return $0 + [$1]
      }
   }
   .map{
     let dayLabel = UILabel()
     let hoursLabel = UILabel()   
     dayLabel.text = $0.0
     hoursLabel.text = $0.1
     daysStack.addArrangedSubview(dayLabel) //or whatever the stackview is called
     hoursStack.addArrangedSubview(hoursLabel)
}

UI 部分过于简单,需要更多才能获得所需的输出,但应该足以开始使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多