Swift Set Array自定义排序

时间:2017-06-21 17:02:26

标签: ios arrays swift sorting

我有联系模式,我希望以[firstLetter, fullName]为{1}}为UITableView排序,方式是{1}}在startIndex,[section,row]在endIndex,在它们之间是排序字母。 例如:"FAVORITES""#"

这是模型

["A", "C", "E", "#", "FAVORITES"]

这是UITableViewController,我在那里对数据进行排序

["FAVORITES", "A", "C", "E", "#"]

编辑#1

抱歉,我忘了说“#”包含fullName以特殊字符开头的联系人

回答我的问题

class Contact: Object {
    dynamic var fullName = ""
    dynamic var firstLetter = ""
}

2 个答案:

答案 0 :(得分:1)

我将如何做到这一点。我必须更改数据结构以进行测试,但您可以将其更改回继承自Object的类。

public extension Sequence {
    public typealias Element = Iterator.Element
    public typealias Group = [Element]

    public func group<Key: Hashable>(by deriveKey: (Element) -> Key) -> [Key: Group] {
        var groups =  [Key: Group]()

        for element in self {
            let key = deriveKey(element)

            if var existingArray = groups[key] { // Group already exists for this key
                groups[key] = nil //performance optimisation to prevent CoW
                existingArray.append(element)
                groups[key] = existingArray
            }
            else {
                groups[key] = [element] // Create new group
            }
        }

        return groups
    }
}


struct Contact: CustomStringConvertible {
    let fullName: String
    let isFavourte: Bool

    var firstLetter: Character {
        return fullName.characters.first!
    }

    var containsSpecialLetters: Bool {
        return false // implement me
    }

    init(_ fullName: String, _ isFavourte: Bool) {
        self.fullName = fullName
        self.isFavourte = isFavourte
    }

    var description: String { return fullName }
}

let contacts = [
    Contact("Alice", false),
    Contact("Alex", false),
    Contact("Bob", true),
    Contact("Bill", false),
    Contact("Cory", false),
    Contact("Casey", true),
    Contact("#åœ∑´ß", false),
    Contact("D", false),
    Contact("E", false),
    Contact("F", false),
    Contact("G", false),
    Contact("H", false),
]


let sections = contacts.group{ contact -> String in
    switch contact {
        case _ where contact.isFavourte: return "Favourites"
        case _ where contact.containsSpecialLetters: return "#"
        case _: return String(contact.firstLetter)
    }
}

let sectionHeaders = sections.keys.sorted {
    //Favourites sorts before all else
    if $0 == "Favourites" { return true }
    if $1 == "Favourites" { return false }

    // Symbols sort after all else
    if $0 == "#" { return false }
    if $1 == "#" { return true }

    return $0 < $1
}

for (sectionHeader, sectionContacts) in sectionHeaders.map({($0, sections[$0]!)}) {
    print("===== \(sectionHeader) =====")
    sectionContacts.forEach{ print($0) }
}

输出:

  

=====收藏夹=====

     

鲍勃

     

凯西

     

===== A =====

     

爱丽丝

     

亚历

     

===== B =====

     

比尔

     

===== C =====

     

科里

     

===== D =====

     

d

     

===== E =====

     

电子

     

===== F =====

     

˚F

     

===== G =====

           

===== H =====

     

ħ

     

=====#=====

     

åœΣ'ß

答案 1 :(得分:0)

如果我了解您要做的事情,您可以先检索您的收藏夹并对其进行排序。

然后检索以#。

开头的那些

之后,您将检索其余部分并对其进行排序。

此时你只需将第三组,然后第二组追加到“收藏夹”数组。

所以结果将是[联系]与FAVORITES首先接触,然后从A开始,用B等开始,最后用#

开头

我假设您已经拥有联系人,因为我从未使用过Realm.io,并且您的联系人或您的表格都有一个isFavorite标志。

伪代码:

func sortContacts(_ aList: [Contact]) -> [Contact]
{
    var retValue = [Contact]()

    var favorites = Set(aList.value(forKeyPath: "isFavorite == true") as![String]).sorted()

    var theRest = Set(aList.value(forKeyPath: "firstLetter") as![String]).sorted()

    retValue.append(favorites)
    retValue.append(theRest)

    return retValue
}

你应该在viewWillAppear中调用它,例如:

func viewWillAppear(animated: Bool)
{
    super.viewWillAppear(animated)
    sections = sortContacts(contacts)

    // code
}