繁体   English   中英

Swift 组合比较字符串

[英]Swift Combine Compare String

我有一个 function 使用组合提供基于用户输入的结果列表。

例如:如果用户键入rain,它将显示一个结果列表,其中包含单词rain。

数据存储在结构中,我需要先匹配一个元素,如果没有匹配,请尝试匹配另一个元素。

例如:

struct dataSet: Codable, Hashable {
    let nameShort: String
    let nameLong: String
}

当用户在表单域中输入一个值时,我希望它先查看nameShort,如果没有结果,再查看nameLong。

等式的第二部分是我需要它使用整个字符串进行匹配,但使用单独的单词。

例如:如果用户输入 brown,它应该通过 nameShort 来查找 brown,然后通过 nameLong 来查找 brown。 但是,如果有大量条目匹配 brown 并且用户然后键入 brown chair,我需要它返回匹配这两个值的结果。

同样,如果用户键入 brow chai,它仍应返回 brown chair,因为初始字符与结构中的单词匹配,即使 nameLong 是 Brown - Side Chair。

这是我当前 function 的示例:

func editingChangedName(_ value: String) {
    $myName
        .debounce(for: 0.3, scheduler: RunLoop.main)
        .receive(on: DispatchQueue.global()) // Perform filter on background
        .map { [weak self] filterString in
            guard filterString.count >= 3, let self = self else { return [] }
            return self.nameArray.filter {
                $0.nameShort
                    .lowercased()
                    .contains(
                        filterString.lowercased()
                    ) ||
                $0.nameLong
                    .lowercased()
                    .contains(
                        filterString.lowercased()
                    )
            }
        }
        .receive(on: RunLoop.main) // Switch back to main thread
        .assign(to: &$allNamesArray)
} // End func

这在表单字段的 onChange 上运行,因此它会不断更新结果。

我试过这样的事情:

let searchString = filterString.lowercased().components(separatedBy: " ")

在保护语句下方,然后从返回中删除 $0.nameShort 和 $0.nameLong ,将其替换为:

searchString.contains(where: $0.nameLong.contains)

但随后所有的结果都变得糟糕透顶。

如果我删除 $0.nameShort 并且只使用 $0.nameLong,并且 change.contains to.hasPrefix 它只会从左到右读取并完全匹配那些存在的字符。 所以,如果我输入 chair,我会得到 0 个结果,而如果我输入 brown,我会得到所有以 brown 开头的结果。

我觉得我很接近,但无法弄清楚如何正确地做到这一点。

在 map 闭合内部试试这个:

let filterComponents = filterString
    .lowercased()
    .components(separatedBy: " ")
return self.nameArray.filter { name in
    return filterComponents.allSatisfy { component in
        return name.nameShort.lowercased().contains(component)
            || name.nameLong.lowercased().contains(component)
    }
}

使用String.components(separatedBy:)提取每个单词。 然后调用allSatisfy检查每个单词是否包含在nameShortnameLong中。

请注意,如果 nameShort 为“brown”且 nameLong 为“chair”,并且您使用“brown chair”作为搜索字符串,则数据集将匹配。 如果您希望所有组件在 nameShort 或 nameLong 中匹配,您必须执行以下操作:

let filterComponents = filterString
    .lowercased()
    .components(separatedBy: " ")
return self.nameArray.filter { name in
    return filterComponents.allSatisfy { component in
        return name.nameShort.lowercased().contains(component)
    } || filterComponents.allSatisfy { component in
        return name.nameLong.lowercased().contains(component)
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM