【问题标题】:How to get unique array in Swift3.0如何在 Swift3.0 中获取唯一数组
【发布时间】:2016-12-07 10:12:23
【问题描述】:

场景,我有一个名为 CommentNSObject 类数组,例如 var comments:[Comment]?。该类具有属性commentBy,它也是一个名为UserNSObject 类,它具有识别唯一用户的属性,即var key:String

以上描述为代码 ,

class Comment:NSObject {
   var commentBy:User?
}
class User:NSObject {
   var key:String?
}
//In some other class
class someClass {
   var comments:[Comment]?
}

我想要什么
我想要一个独特的评论数组,假设userA 发表了 2 条 cmets,userB 发表了 1 条评论,所以总共有 3 个 cmets,但是 在我的独特数组中,我想显示两个用户制作了 cmets

我该怎么办?

【问题讨论】:

  • 这与标题中提到的“NSSet”有关吗?
  • 为什么 Comment 和 User 派生自 NSObject?我认为将它们设为Structs 会更好
  • 为什么commentBy 是可选的?几乎没有没有作者的 cmets。
  • @vadian 我想他们是可选的,以解决没有初始化程序的错误:D 而不是创建初始化程序:)
  • @Fogmeister 是的,很可能是另一个 path-of-least-resistance-optional ;-)

标签: arrays swift3 ios10


【解决方案1】:
var comments: [Comment]?
let userKeys = comments?.flatMap { $0.commentBy?.key } ?? []
let set = Set(userKeys)

如果您想要的只是评论过的唯一用户总数,那么我认为将 cmets 映射到用户的密钥然后创建一组密钥会更快。

【讨论】:

    【解决方案2】:

    看看我在做什么,其实你的问题是How to init a NSSet in swift

    class Comment:NSObject {
        var commentBy:User?
    }
    class User:NSObject {
        var key:String?
    }
    //In some other class
    class someClass {
        var comments:[Comment]?
    }
    
    let user1 = User()
    user1.key = "1"
    let user2 = User()
    user1.key = "2"
    
    let c1 = Comment()
    c1.commentBy = user1
    let c2 = Comment()
    c2.commentBy = user1
    let c3 = Comment()
    c3.commentBy = user2
    
    
    let set: NSSet = [user1, user2]
    let set2: NSSet = [user2]
    set2.isSubset(of: set as! Set<AnyHashable>) //true
    
    let set3: NSSet = [c1, c1]
    set3.count //1
    let set4: NSSet = [c1, c2, c3] // your unique array
    let set5 = NSSet(array: [c1, c2, c1, c3])
    set5.count //3
    

    set3 将始终为[c1],因为SetNSSet 中的元素将是唯一的。

    【讨论】:

      【解决方案3】:

      首先使User 可散列化,以使它们基于它们的唯一键相等。

      class User: NSObject
      {
          let key:String
      
          init(key: String) { self.key = key }
      
          override func isEqual(_ object: Any?) -> Bool
          {
              guard let other = object as? User else { return false }
              return self.key == other.key
          }
          override var hashValue: Int { return key.hashValue }
      }
      
      let eq = User(key: "foo") == User(key: "foo") // true
      let h1 = User(key: "foo").hashValue           // some big number
      let h2 = User(key: "foo").hashValue           // same big number as above
      

      我将key 设置为不可变的,因为它用于唯一标识用户,因此不可能更改。

      因为UserNSObject,它已经有一个使用isEqual:== 实现,因此您可以覆盖它以根据键进行比较。您还可以使用keyhashValue 作为User 哈希值。

      现在您可以在集合中使用User,也可以在字典中使用User。如果您对Comment 执行相同操作,以便它们在User 上比较相等,您也可以在集合中使用 cmets。然而,这是一个坏主意。两个 cmets 并不相同,因为它们具有相同的用户。您应该更改 SomeClass 以使用用户键入的字典,如下所示:

      class Comment: NSObject
      {
          let user: User
          let text: String
      
          init(user: User, text: String)
          {
              self.user = user
              self.text = text
          }
      }
      
      class SomeClass
      {
          var userComments: [User : [Comment]] = [:]
      
          func addComment(newComment: Comment)
          {
              if let existingComments = userComments[newComment.user]
              {
                  userComments[newComment.user] = existingComments + [newComment]
              }
              else
              {
                  userComments[newComment.user] = [newComment]
              }
          }
      
          var userCount: Int { return userComments.count }
          var commentCount: Int { return userComments.values.reduce(0, { $0 + $1.count}) }
      }  
      

      属性 userCount 是您要求的数字。属性 commentCount 是 cmets 的总数 - 尽管要注意:实现在 O(n) 时间内运行。如果速度至关重要,您应该维护一个计数器,每次添加评论时都会递增。

      【讨论】:

        猜你喜欢
        • 2023-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-28
        • 2010-09-10
        • 2014-11-03
        • 2012-05-11
        相关资源
        最近更新 更多