首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >字典扩展sortInPlace的快速数组

字典扩展sortInPlace的快速数组
EN

Stack Overflow用户
提问于 2015-10-22 14:47:57
回答 3查看 620关注 0票数 0

使用SWIFT2.1,我尝试创建一个函数,根据键dateKey的日期值对字典数组进行排序。

我想把它作为一个扩展添加到数组类型中,所以我可以使用someArray.sortDictionariesByDate(dateKey: String, dateFormatter: NSDateFormatter)调用它

代码语言:javascript
复制
extension Array where Element: CollectionType {
  mutating func sortDictionariesByDate(dateKey: String, dateFormatter: NSDateFormatter) {
    sortInPlace {
      dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
      if let dateStringA: String = ($0 as? [String: AnyObject])?[dateKey] as? String, let dateStringB = ($1 as? [String: AnyObject])?[dateKey] as? String {
        if let dateA: NSDate = dateFormatter.dateFromString(dateStringA), dateB: NSDate = dateFormatter.dateFromString(dateStringB) {
          return dateA.compare(dateB) == .OrderedAscending
        }
      }
      return false
    }
  }
}

只要字典被键入为[String: AnyObject],它就能正常工作,但是如果我在[String: String]类型的字典上使用它,它就不能工作,因为它无法将String转换为AnyObject。我认为这是因为StringStruct,而不是Class。我还尝试将元素类型转换为[String: Any],但是不管使用[String: AnyObject][String: String]类型的字典,它都无法工作。

是否有任何cast可以用来支持键类型String和任何值类型(StringAnyObject等)的字典,或者可以添加到扩展中以避免完全转换的where子句或协议一致性?

编辑:下面是两个示例数组,每个请求

代码语言:javascript
复制
var sampleArray1: [[String: AnyObject]] = [["date": "2015-10-24T13:00:00.000Z", "foo": "bar"], ["date": "2015-10-24T14:00:00.000Z", "foo": "bar"]]
sampleArray1.sortDictionariesByDate("date", dateFormatter: NSDateFormatter())
var sampleArray2: [[String: String]] = [["date": "2015-10-24T13:00:00.000Z", "foo": "bar"], ["date": "2015-10-24T14:00:00.000Z", "foo": "bar"]]
sampleArray2.sortDictionariesByDate("date", dateFormatter: NSDateFormatter())
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-10-22 20:42:33

第一个问题:你在比较字符串,而不是日期。幸运的是,您的字符串格式使其与字符串和它所代表的日期值都具有直接可比性。因此,您根本不需要将其转换为NSDate

第二个问题是,将Dictionary<Key,Value1>类型转换为Dictionary<Key,Value2>批发是不起作用的,即使Value1协变 on Value2。它可能在这样的小例子中起作用..。

代码语言:javascript
复制
let a : [String: String] = ["name": "David", "location": "Chicago"]
let b = a as [String: AnyObject]

...because编译器可以在a中看到值类型(String),并通过编译时对其进行优化。对于像您这样的动态情况,没有提前可用的信息。

当你需要活力时,你总是可以回到老朋友的身边,目标C:

代码语言:javascript
复制
extension Array where Element: CollectionType {
    mutating func sortDictionariesByDate(dateKey: String) {
        self.sortInPlace {
            if let a = $0 as? NSDictionary, b = $1 as? NSDictionary {
                return (a[dateKey] as? String) < (b[dateKey] as? String)
            } else {
                return false
            }
        }
    }
}

// Example:
var sampleArray1: [[String: AnyObject]] = [
    ["date": "2015-10-24T13:00:00.000Z", "foo": "bar"],
    ["date": "2015-10-24T14:00:00.000Z", "foo": "bar"],
    ["date": "2015-10-24T10:00:00.000Z", "foo": "bar"]
]
var sampleArray2: [[String: String]] = [
    ["date": "2015-10-24T13:00:00.000Z", "foo": "bar"], 
    ["date": "2015-10-24T14:00:00.000Z", "foo": "bar"],
    ["date": "2015-10-24T10:00:00.000Z", "foo": "bar"]
]

sampleArray1.sortDictionariesByDate("date")
sampleArray2.sortDictionariesByDate("date")

注意,由于您现在比较的是字符串而不是日期,所以不需要NSDateFormatter

票数 2
EN

Stack Overflow用户

发布于 2015-10-22 20:59:58

你要做的事太傻了。在没有强制转换的情况下,您不会编写一个同时在[[String:AnyObject]][[String:String]]上工作的函数。斯威夫特打字很严格。事情就是这样。演员们,开心点!

转换像字典这样的复杂类型的数组的诀窍是使用map分别对每个元素进行强制转换(这实际上是数组转换在幕后所做的):

代码语言:javascript
复制
let sampleArray1: [[String: AnyObject]] = [["date": "2015-10-24T13:00:00.000Z", "foo": "bar"], ["date": "2015-10-24T14:00:00.000Z", "foo": "bar"]]
let sampleArray2: [[String: String]] = [["date": "2015-10-24T13:00:00.000Z", "foo": "bar"], ["date": "2015-10-24T14:00:00.000Z", "foo": "bar"]]

func sortByDate(arr:[[String:AnyObject]]) -> [[String:AnyObject]] {
    let result = arr.sort {
        d1, d2 in
        let dat1 = NSDateFormatter().dateFromString(d1["date"] as! String)!
        let dat2 = NSDateFormatter().dateFromString(d2["date"] as! String)!
        return dat1.timeIntervalSinceReferenceDate < dat2.timeIntervalSinceReferenceDate
    }
    return result
}

let arr1 = sortByDate(sampleArray1)
let arr2 = sortByDate(sampleArray2.map{$0 as [String:AnyObject]})
// and if you have to, `map` arr2 back down to [String:String]

我承认我没有完全填写规范,但是很容易添加更多的参数,这样就可以提供密钥名和格式化程序。请注意,这个示例实际上会使您的数据崩溃,因为我们没有匹配的日期格式。您需要提供有效的格式。

我还认为(作为同一观点的一部分),将日期字符串放入字典而不是实际日期是愚蠢的。但我只是为了争论才同意这个前提。

票数 1
EN

Stack Overflow用户

发布于 2015-10-22 22:17:51

这里有一个不同的解决方案,在处理函数内的转换时,将函数保留为Array的扩展,从而避免在处理不同类型的字典时来回使用.map()。缺点是您必须事先知道函数支持的类型,而@matt的解决方案允许您在调用该方法时处理转换,而代价是不作为扩展、不按位置排序和来回映射。

代码语言:javascript
复制
extension Array where Element: CollectionType {
  mutating func sortDictionariesByDate(dateKey: String, dateFormatter: NSDateFormatter) {
    sortInPlace {
      dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
      var dateString1: String?
      var dateString2: String?

      if let a = $0 as? [String: AnyObject], let b = $1 as? [String: AnyObject] {
        if let dateStringA: String = a[dateKey] as? String, dateStringB: String = b[dateKey] as? String {
          dateString1 = dateStringA
          dateString2 = dateStringB
        }
      } else if let a = $0 as? [String: String], let b = $1 as? [String: String] {
        dateString1 = a[dateKey]
        dateString2 = b[dateKey]
      }

      if let dateString1: String = dateString1, let dateString2: String = dateString2 {
        if let date1: NSDate = dateFormatter.dateFromString(dateString1), date2: NSDate = dateFormatter.dateFromString(dateString2) {
          return date1.timeIntervalSinceReferenceDate < date2.timeIntervalSinceReferenceDate
        }
      }
      return false
    }
  }
}

// Example:
var sampleArray1: [[String: AnyObject]] = [
    ["date": "2015-10-24T13:00:00.000Z", "foo": "bar"],
    ["date": "2015-10-24T14:00:00.000Z", "foo": "bar"],
    ["date": "2015-10-24T10:00:00.000Z", "foo": "bar"]
]
var sampleArray2: [[String: String]] = [
    ["date": "2015-10-24T13:00:00.000Z", "foo": "bar"], 
    ["date": "2015-10-24T14:00:00.000Z", "foo": "bar"],
    ["date": "2015-10-24T10:00:00.000Z", "foo": "bar"]
]

sampleArray1.sortDictionariesByDate("date")
sampleArray2.sortDictionariesByDate("date")
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33283919

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档