如何使用Swift3将数据从NSMutableArray填充到struct中

时间:2016-11-12 16:38:40

标签: ios swift3

我创建了一个结构体,我希望用我的数据填充它。

我的结构:

struct CrimeNameSection {

var firstChar: Character
var name: [String]
var detail: [String]
var time: [String]


init(firstLetter: Character, object1: [String], object2: [String], object3: [String]) {

    firstChar = firstLetter // First letter of 'name'
    name = object1
    detail = object2
    time = object3
}

我的结构的第一个值(' firstChar')应该在' name'中保留第一个字母。要在tableView中创建字母部分,其余部分('名称','详细信息'时间')应保存数据库中的数据(三列:名称,细节,时间)。

我的代码:

var marrCrimesData : NSMutableArray! // Hold the database

func getSectionsFromData() -> [CrimeNameSection] {
    guard marrCrimesData != nil else {
        return []
    }


    var sectionDictionary =  [CrimeNameSection]()
    for crime in marrCrimesData {
        let crime = crime as! CrimesInfo
        let firstChar = CrimeNameSection(firstLetter: crime.name[crime.name.startIndex], object1: [crime.name], object2: [crime.detail], object3: [crime.time])
        if var names = firstChar {
            names.append(crime.name)
            sectionDictionary[firstChar] = names
        } else {
            sectionDictionary[firstChar] = [crime.name]
        }
    }

    let sections = sectionDictionary.map { (key, value) in
        return CrimeNameSection(firstLetter: key, name: value)
    }
    let sortedSections = sections.sorted { $0.firstLetter < $1.firstLetter }

    return sortedSections 
}

我在整个地方都遇到错误,我需要帮助将数据存储在我的结构中并按字母顺序排序。 谢谢大家

2 个答案:

答案 0 :(得分:1)

首先,您无法实例化数组并将其映射为字典

var sectionDictionary = [CrimeNameSection]() // Here you are init an Array

对于字典,您还必须指定密钥,例如,如果密钥是字符串:

var sectionDictionary = [String: CrimeNameSection]() // Dictionary init

但请注意,密钥必须是唯一的才能使dict正常工作 这里的另一个问题是你的.map函数中的构造函数,因为你没有为CrimeNameSection创建一个只带两个参数的构造函数:

init(firstLetter: Character, object1: [String], object2: [String], object3: [String]) {

    firstChar = firstLetter // First letter of 'name'
    name = object1
    detail = object2
    time = object3
}

// Another constructor with 2 arguments
 init(firstLetter: Character, object1: [String]) {

    firstChar = firstLetter // First letter of 'name'
    name = object1
    detail = []()
    time = []()
}

如果您不想使用其他构造函数,则必须在初始构造函数中为object2和object3提供默认值。

答案 1 :(得分:1)

考虑

struct Crime {
    let name: String
    let detail: String
    let time: String
}

let crimes = [
    Crime(name: "Foo", detail: "detail 1", time: "9am"),
    Crime(name: "Bar", detail: "detail 2", time: "10am"),
    Crime(name: "Baz", detail: "detail 3", time: "11am"),
    Crime(name: "Qux", detail: "detail 4", time: "12am")
]

一种方法是只构建一个由第一个字符索引的字典,然后对其进行排序:

var crimeIndex = [Character: [Crime]]()
for crime in crimes {
    if let firstCharacter = crime.name.characters.first {
        if crimeIndex[firstCharacter] == nil {
            crimeIndex[firstCharacter] = [crime]
        } else {
            crimeIndex[firstCharacter]?.append(crime)
        }
    }
}

let sortedIndex = crimeIndex.sorted { $0.0 < $1.0 }

以上的优点是我们可以使用字典来有效地找到该部分。如果你真的想使用你的自定义“名称部分”结构,我首先要使用Crime个对象的数组(具有Crime属性的脱节数组可能是脆弱的,例如如果你以后决定添加犯罪分类)。所以它可能看起来像:

struct CrimeNameSection {
    let firstCharacter: Character
    var crimes: [Crime]
}

因为我们已经失去了查找索引的一些Dictionary效率,并且手动迭代查找该部分,我将继续进行插入排序,从而节省了我以后必须单独排序:

var crimeSections = [CrimeNameSection]()
for crime in crimes {
    if let firstCharacter = crime.name.characters.first {
        var hasBeenAdded = false

        for (index, crimeIndex) in crimeSections.enumerated() {
            if firstCharacter == crimeIndex.firstCharacter {  // if we found section, add to it
                crimeSections[index].crimes.append(crime)
                hasBeenAdded = true
                break
            }
            if firstCharacter < crimeIndex.firstCharacter {   // if we've passed where the section should have been, insert new section
                crimeSections.insert(CrimeNameSection(firstCharacter: firstCharacter, crimes: [crime]), at: index)
                hasBeenAdded = true
                break
            }
        }

        // if we've gotten to the end and still haven't found section, add new section to end

        if !hasBeenAdded {
            crimeSections.append(CrimeNameSection(firstCharacter: firstCharacter, crimes: [crime]))
        }
    }
}