Swift: фильтр в словаре, сгруппированный по ключу - PullRequest
0 голосов
/ 10 января 2020

Моя цель - иметь возможность фильтровать по имени в словаре, сгруппированном по ключу, и видеть результаты, отфильтрованные по тексту, введенному в поле поиска. Я остановился на:

var groupedContacts: [String: [CNContact]] {
    .init (
        grouping: store.contacts,
        by: {$0.nameFirstLetter}
    )
}

func filterContactsByName(_ textSearch: String) -> [String: [CNContact]]  {
    let contacts = groupedContacts

    if !textSearch.isEmpty {
        return contacts.compactMapValues{$0.filter {$0.name.localizedCaseInsensitiveContains(textSearch)}}.filter{!$0.value.isEmpty}

    } else {
       return contacts
    }
}

А потом:

 List() {
                        ForEach(self.filterContactsByName(searchText).keys.sorted(), id: \.self) { key in
                        Section(header: Text(key).modifier(SectionHeader(backgroundColor: Color.white, foregroundColor: Color.black))) {
                            ForEach(self.groupedContacts[key]!, id: \.self) { contact in
                                HStack {
                                    self.image(for: contact.imageProfile)
                                        .renderingMode(.original)
                                        .resizable()
                                        .scaledToFill()
                                        .frame(width: 40, height: 40)
                                        .aspectRatio(contentMode: .fit)
                                        .clipShape(Circle())

Мой результат: снимок экрана

Как я понял, я получил все результаты в ключевой группе, поэтому мы видим Даниал перед Дэвидом. И это будет то же самое, если мы введем Дэвида - мы увидим Даниал. ТИА за помощь.

1 Ответ

1 голос
/ 10 января 2020

Вам нужно отфильтровать правильную группу, а затем отфильтровать внутри этой группы. В приведенном ниже коде, который несколько упрощен, поскольку я использовал String вместо CNContact и не беспокоился о поиске без учета регистра, я сначала нахожу группу путем фильтрации по первому символу строки поиска, а затем я использовал reduce(into:) в комбинации с filter для фильтрации массива по найденному ключу.

var groupedContacts: [String: [String]] = ["D": ["David", "Daniel"], "A": ["AAA"]]
let filter = "Dav"

let results = groupedContacts.filter { $0.key == filter.prefix(1) }
    .reduce(into: [:]) {$0[$1.key] = $1.value.filter { $0.hasPrefix(filter)}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...