【问题标题】:How to insert different type of element in array如何在数组中插入不同类型的元素
【发布时间】:2019-06-21 10:15:55
【问题描述】:

我有一个class,它引用了另一个class。学生类有一个引用模块信息的变量。我想将moduleId 插入到数组中,但该结构由不同类型的对象组成,并且是moduleRef 类型。我想获得字符串类型的moduleId。我怎样才能从ModuleRef 中获取这个moduleId 元素。

class Student {
    var firstName: String
    var lastName: String
    var modulesRefs: [ModuleRef]

    var fullName: String {
        return self.firstName + " " + self.lastName
    }

    init(firstName: String, lastName: String, modulesRefs: [ModuleRef]) {
        self.firstName = firstName
        self.lastName = lastName
        self.modulesRefs = modulesRefs
    }

    func addModuleId(_ moduleId: String) {
        self.modulesRefs.insert(moduleId, at: 0)
    }

     func removeModuleId(_ moduleId: String) {
        self.modulesRefs = self.modulesRefs.filter { $0.moduleId != moduleId }
    }
}

class ModuleRef {
    var moduleName: String
    var moduleId: String
    var moduleStartdate: Int

    init(moduleName: String, moduleId: String, moduleStartdate: Int) {
        self.moduleName = moduleName
        self.moduleId = moduleId
        self.moduleStartdate = moduleStartdate
    }
}

无法将“String”类型的值转换为预期的参数类型“ModuleRef”

【问题讨论】:

  • 能否请您也显示插入方法?
  • @SohilR.Memon insertSwift's standard library
  • 您正在调用addModuleId 插入新值?
  • @SohilR.Memon 是的。这是一个字符串
  • moduleName & moduleStartdate 呢,当你只传递moduleId 时,这两个变量的值是多少?

标签: ios arrays swift filter


【解决方案1】:

您可以将类型ModuleRef 的值插入到该数组中。所以我可以将函数修改为:

func addModuleId(_ moduleId: String) {
        let module = ModuleRef(moduleName: "", moduleId: moduleId, moduleStartdate: 0)
        self.modulesRefs.insert(module, at: 0)
    }

    func removeModuleId(_ moduleId: String) {
        modulesRefs.removeAll(where: { $0.moduleId == moduleId })
    }

注意:如果您一直不需要moduleNamemoduleStartdate,可以将其标记为可选。

【讨论】:

    【解决方案2】:

    在您的代码中,您已强制设置 class ModuleRef { ... } 值,而您只是传递了一个值 moduleId 并将其添加到 ModuleRefArray 中,这是完全错误的方法。所以,根据你在这里所说的是你的代码的更新代码:

    class Student {
        var firstName: String
        var lastName: String
        var modulesRefs: [ModuleRef]
    
        var fullName: String {
            return self.firstName + " " + self.lastName
        }
    
        init(firstName: String, lastName: String, modulesRefs: [ModuleRef]) {
            self.firstName = firstName
            self.lastName = lastName
            self.modulesRefs = modulesRefs
        }
    
        func addModuleId(_ moduleId: String) {
            // This will be your updated intializer where you can pass any value you want and other will be taken as default value
            let moduleRef = ModuleRef(moduleId: moduleId)
            self.modulesRefs.insert(moduleRef, at: 0)
        }
    
        func removeModuleId(_ moduleId: String) {
            self.modulesRefs = self.modulesRefs.filter { $0.moduleId != moduleId }
        }
    }
    
    class ModuleRef {
        var moduleName: String
        var moduleId: String
        var moduleStartdate: Int
    
        /// Here you can provide all the default values which you don't want to pass
        init(moduleName: String = "", moduleId: String = "", moduleStartdate: Int = 0) {
            self.moduleName = moduleName
            self.moduleId = moduleId
            self.moduleStartdate = moduleStartdate
        }
    }
    

    此外,您还可以将nil 值传递给所有将变量设为optional。如果您有任何困惑,请告诉我!

    【讨论】:

      【解决方案3】:

      您不能仅通过传递String 来插入ModuleRef

      您需要创建一个实例,例如添加学生的全名和当前日期的 UNIX 时间戳

      func addModuleId(_ moduleId: String) {
          let moduleRef = ModuleRef(moduleName: self.fullName, 
                                    moduleId: moduleId, 
                                    moduleStartDate: Int(Date().timeIntervalSince1970))
          self.modulesRefs.insert(moduleRef, at: 0)
      }
      

      并且要删除一个对象,这更有效,但是该类必须符合Equatable

      func removeModuleId(_ moduleId: String) {
          guard let index = self.modulesRefs.firstIndex(where: {$0.moduleId == moduleId}) else { return }
          self.modulesRefs.remove(at: index)
      }
      

      我什至会将moduleStartDate 声明为Date

      【讨论】:

      • 这很好,但如果我只想要 moduleRef 对象中的 moduleId 怎么办。我怎样才能做到这一点。我不能仅仅排除它们。会告诉我一个错误告诉我invalid number of arguments
      • 你到底要在addModuleId 方法中完成什么?考虑modulesRefs 数组包含多个ModuleRef 对象,它们分别具有3 个属性。
      • 不用担心,我已经为其余部分设置了默认值。谢谢。
      【解决方案4】:

      您需要将 Array 类型更新为 Any,如下所示:

      var modulesRefs: [Any] 
      

      从数组中访问值时,

      if let moduleRef = modulesRefs[index] as? ModuleRef {
      
      } else if let str = modulesRefs[index] as? String  {
      
      }
      

      【讨论】:

      • 不要使用Any。只有两种不同的类型使用通用协议。
      • @vadian 这也让我感到困惑,如果我想从另一个班级获得moduleId,为什么我会这样做
      【解决方案5】:

      你试图做的,实际上意味着你的设计存在缺陷。

      如果您需要调用student.addModuleId(moduleId) 的功能,这意味着Student 不应包含ModuleRef 的数组。 (或者至少有一种机制可以通过它的 id 获取整个 ModuleRef,然后将 ModuleRef 插入到数组中)

      话虽如此,在弄清楚你的设计将是:modules: [ModuleRef]moduleIds: [String],你仍然可以使用一些东西:

      Equatable 协议。如果你让ModuleRef 符合Equatable 协议,并检查它与id 的相等性,那么Swift 将允许你访问remove(element:_) 方法,你不再需要removeModuleId() 方法。

      或者如果所有ModuleIds 都是唯一的,您也可以实现Hashable 协议,并使用Set<ModuleRef> 代替数组来获得O(1) 的删除和插入方法。 (现在,删除函数,需要 O(n) 时间)

      【讨论】:

        【解决方案6】:

        你需要创建一个 Any 类型的数组..

        var modulesRefs: [Any] = []
        

        你可以像这样在数组中添加元素...

        modulesRefs.append("Test string")
        let obj = ModuleRef(...)
        modulesRefs.append(obj)
        

        当您访问一个元素时,您需要使用if letguard let 来安全地检查其类型。

        例如。

          for obj in modulesRefs {
            if let strType = obj as? String {
               print("\(obj) is string type")
            } else if let moduleRefObj = obj as? ModuleRef {
               print("\(obj) is ModuleRef type")
          }
        

        【讨论】:

        • 不要使用Any。只有两种不同的类型使用通用协议。
        猜你喜欢
        • 2018-07-20
        • 2019-06-25
        • 2019-06-14
        • 1970-01-01
        • 1970-01-01
        • 2015-04-26
        • 2022-10-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多