【问题标题】:Group elements with the same property value from an array [duplicate]对数组中具有相同属性值的元素进行分组[重复]
【发布时间】:2017-06-02 12:51:39
【问题描述】:

我有一个数组[modelA,modelB,modelC,modelD,modelE],数组中的每个元素都是一个Struct的实例。结构有一个属性“名称”。比如……

modelA.name = "abc"
modelB.name = "efg" 
modelC.name = "hij"    
modelD.name = "abc"
modelE.name = "efg"

如何将具有相同属性值的元素分组到一个新数组中?即将modelA和modelD放入一个新数组,将modelB和modelE放入另一个数组

假设原始数组是

【问题讨论】:

  • var d[String: [Model]]; for i in array { let m = array.filter { $0.name == i.name }; if m.count > 1 { d[i.name] = m }} 会有什么问题?
  • stackoverflow.com/questions/31220002/…这解决了我的问题,谢谢大家

标签: ios arrays swift


【解决方案1】:

您可以使用filter(_:)

返回一个按顺序包含序列元素的数组 满足给定谓词。

例如,考虑结构如下:

struct Model {
    var name: String?
}

你有一个模型数组:

let allModelsArray = [Model(name: "abc"), Model(name: "efg"), Model(name: "hij"), Model(name: "abc"), Model(name: "efg"), Model(name: "efg"), Model(name: "hij")]

因此,您可以通过以下方式获取您的数组(假设您要根据name 的值进行过滤):

let abcModelsArray = allModelsArray.filter { $0.name == "abc" }
// [Model(name: Optional("abc")), Model(name: Optional("abc"))]

let hijModelsArray = allModelsArray.filter { $0.name == "hij" }
// [Model(name: Optional("hij")), Model(name: Optional("hij"))]

另外:

你提到过:

如何将具有相同属性值的元素放入新的 数组,比如把modelA和modelD放到一个新数组中,把modelB 并将 modelE 放入一个新数组中,如果数组很大

不知何故,您可能想要使用集合的lazy 版本。

希望这会有所帮助。

【讨论】:

  • 为此,您必须知道所有开头的名称。这充其量是 O(n^2)。我认为@Grimxn 评论是一个更好的解决方案,它会是 O(n)。
  • @Fogmeister - 感谢您的评论,但我的仍然是 O(n^2),因为 filter 本身是 O(n),乘以 for 循环...
  • @Grimxn 我的意思是你留下的评论。没看到你的回答。 :-) 哦。另外,我误读了您的评论:-)
【解决方案2】:

我没有对此进行性能测试

struct Model {
    var type : String
    var name : String
}
var modelA = Model(type: "A", name: "abc")
var modelB = Model(type: "B", name: "efg")
var modelC = Model(type: "C", name: "abc")
var modelD = Model(type: "D", name: "efg")

let models = [modelA,modelB,modelC,modelD]

let names = Set(models.map({return $0.name}))

var groupedModels : [String:[Model]] = [:]
for var name in names {
    let elements = models.filter({$0.name == name})
    groupedModels[name] = elements
}

【讨论】:

  • 你的答案的好部分是你假设name 是未知的,我觉得这更合乎逻辑。
【解决方案3】:

.reduce解决方案:

let a = [modelA, modelB, modelC, modelD, modelE]

let arr = a.reduce([:]) { (result, currentModel) -> [String: [Model]] in
    var mutableDic = result
    if ((mutableDic[currentModel.name]) != nil) {
        mutableDic[currentModel.name]?.append(currentModel)
    } else {
        mutableDic[currentModel.name] = [currentModel]
    }

    return mutableDic
}

它将返回与@Grimxn 响应相同的字典。或者从这个for loop得到的

var mutableDic = [String : [Model]]()

        for aModel in a {
            if ((mutableDic[aModel.name]) != nil) {
                mutableDic[aModel.name]?.append(aModel)
            } else {
                mutableDic[aModel.name] = [aModel]
            }
        }

关键是使用字典来跟踪需要放在同一数组中的模型,通过比较它的.name

【讨论】:

  • 这似乎比我的更好,因为乍一看它是 O(n)。
  • Nit 采摘,但它的返回值与我的不完全相同,因为我的仅包含多次引用的名称...
猜你喜欢
  • 2018-10-24
  • 2018-01-21
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
  • 2017-03-18
  • 2021-12-04
  • 1970-01-01
相关资源
最近更新 更多