Как считать дубликаты и показывать их как одно - PullRequest
0 голосов
/ 06 февраля 2020

У меня есть класс объектов с именем Students, в котором у меня есть Student Name, Contact и Twitter Handle. Теперь, когда я получаю эти данные из базы данных, я сохраняю их в массиве var students: [Student] = []. Используя firestore, я запускаю запрос и сохраняю результаты в массиве как:

let studentObj = Student(dictionary: querySnapShot.data()!)
self.students.append(studentObj!)

Внутри querySnapShot.data() данные учеников могут быть дублированы. Это означает, что могут быть похожие ученики, которые появляются более одного раза.

Я хочу сосчитать этих дублирующих учеников, например, если Ava - это три раза в данных, он должен считать и отображать как Ava (3) в ячейка таблицы Я сделал это, используя словарь var studentCapCount = [String: Int]() и функцию:

func countStudents(studentArray: [Student]) {
    for item in studentArray {

        studentCapCount[item.name] = studentCapCount[item.name] ?? 0 + 1
    }
    self.tableView.reloadData()
}

Проблема:

Функция рассчитывает правильно, но когда дело доходит до отображения, есть проблема. Поскольку я использую только item.name, поэтому я не могу понять, как показать имя студента , контакт и твиттер в cellForRowAt методе tableView. Как то, что я должен написать здесь:

    cell.textLabel?.text =  ??
    cell.detailTextLabel?.text = "Contact: \(students[indexPath.row].contact) | Twitter: \(students[indexPath.row].twitter)"

Если я верну students.count в numberOfRowsInSection, это проблема, потому что она также будет включать подсчет повторяющихся значений, но если я сделаю studentCapCount.count, это также проблема, потому что Я не могу напечатать detailTextLabel?.text из-за нет. строк.

Код класса ученика:

struct Student {

    var name: String
    var contact: String
    var twitter: String


    var dictionary: [String: Any] {
        return [
            "name": name,
            "contact": contact,
            "twitter": twitter
        ]
    }
}

extension PoliticianMarker {
    init?(dictionary: [String: Any]) {
        let name = dictionary["name"] as? String,
        let contact = dictionary["contact"] as? String,
        let twitter = dictionary["twitter"] as? String
            else {
            return nil
        }
        self.init(name: name, contact:contact, twitter:twitter)
    }
}

1 Ответ

1 голос
/ 06 февраля 2020

Соответствует Student Hashable и реализует == и hash(into:) методы,

struct Student: Hashable {
    var name: String
    var contact: String
    var twitter: String

    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
        hasher.combine(contact)
        hasher.combine(twitter)
    }

    static func == (lhs: Student, rhs: Student) -> Bool {
        return lhs.name == rhs.name && lhs.contact == rhs.contact && lhs.twitter == rhs.twitter
    }
}

Теперь вы можете сгруппировать дубликаты Student, используя Dictionary's init(grouping:by:), то есть

var students = [Student(name: "Alex", contact: "1234", twitter: "XYZ"), Student(name: "Alex", contact: "1234", twitter: "XYZ"), Student(name: "Mike", contact: "98765", twitter: "XYZ"), Student(name: "Mike", contact: "09876", twitter: "PQR")]

let dict = Dictionary(grouping: students, by: { $0.hashValue })

Далее, получите students из dict, используя compactMap(_:), например,

students = dict.compactMap({
    var countText = ""
    if $0.value.count > 1 {
        countText = " x\( $0.value.count)"
    }
    var student = $0.value.first
    student?.name += countText
    return student
})

Наконец , используйте students как ваш tableView's dataSource.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...