检查字符串是否包含Swift中的可选字符串,但仅当它为';不是零
我想向处理字符串列表的函数添加一个可选的“filter”参数。如果筛选器为检查字符串是否包含Swift中的可选字符串,但仅当它为';不是零,swift,Swift,我想向处理字符串列表的函数添加一个可选的“filter”参数。如果筛选器为nil,我希望处理所有字符串,否则我只希望处理包含筛选器的字符串。大致: func process(items: [String], filter: String?) { for item in items { if filter == nil || item.contains(filter) { // Do something with item } } } typechecker抱
nil
,我希望处理所有字符串,否则我只希望处理包含筛选器的字符串。大致:
func process(items: [String], filter: String?) {
for item in items {
if filter == nil || item.contains(filter) {
// Do something with item
}
}
}
typechecker抱怨将筛选器传递到contains
,因为它是可选的,但是contains
使用字符串。我当然可以强行打开,但那看起来很难看。上面的代码将用Kotlin编译,因为它会去掉可选的,但是用Swift表达这一点的惯用方式是什么呢
谢谢 可选项上有一个映射
,仅当可选项不是nil
时才执行提供的闭包。如果map
返回nil
,则可以使用map
和nil合并运算符??
提供true
的默认值,因为过滤器是nil
:
func process(items: [String], filter: String?) {
for item in items {
if filter.map(item.contains) ?? true {
// process item
}
}
}
Optional上有一个map
,仅当可选项不是nil
时才执行提供的闭包。如果map
返回nil
,则可以使用map
和nil合并运算符??
提供true
的默认值,因为过滤器是nil
:
func process(items: [String], filter: String?) {
for item in items {
if filter.map(item.contains) ?? true {
// process item
}
}
}
这里的关键是(并且将一直是)零聚结操作符。如果可选值不是nil
,则可以安全地展开它,但如果它是nil
,则可以替换另一个值
然而,这个问题的问题是,它以一种不坚定的方式出现。您永远不会编写接受可选字符串的筛选函数。您可以编写一个过滤函数,该函数采用可选的过滤函数!您希望允许任何类型的数组和任何过滤函数,而不是将调用者限制为包含和字符串。这是编写此函数的快捷方式
当我们在做这个时,函数也不应该预先决定对数组的成员做了什么。这应该是调用方传入的另一个函数
因此,我们最终对目标做出了更一般、更迅速的陈述:
func process<T>(_ arr: [T],
filtering filterPred: ((T)->Bool)? = nil,
processing processPred: ((T)->Void)) {
// ...
}
非常好!但是我们忽略了处理过滤函数。让我们来解决这个问题。显然,这是橡胶与道路的交汇点。同样清楚的是,这是一个要传递到过滤器中的函数。但是,我们只能在它不是nil
的情况下通过展开来实现这一点。如果是nil
,该怎么办?OP已经指定,在这种情况下,我们应该让所有元素通过过滤器
请考虑一个谓词函数,它将被传递到<代码>筛选器< /代码>。什么是让一切通过的功能?它是:
{ _ in true }
这就是在nil凝聚算子之后要做的!因此,这是完整的答案:
func process<T>(_ arr: [T],
filtering filterPred: ((T)->Bool)? = nil,
processing processPred: ((T)->Void)) {
arr.filter(filterPred ?? { _ in true }).forEach(processPred)
}
这里的关键是(并且将一直是)零聚结操作符。如果可选值不是nil
,则可以安全地展开它,但如果它是nil
,则可以替换另一个值
然而,这个问题的问题是,它以一种不坚定的方式出现。您永远不会编写接受可选字符串的筛选函数。您可以编写一个过滤函数,该函数采用可选的过滤函数!您希望允许任何类型的数组和任何过滤函数,而不是将调用者限制为包含和字符串。这是编写此函数的快捷方式
当我们在做这个时,函数也不应该预先决定对数组的成员做了什么。这应该是调用方传入的另一个函数
因此,我们最终对目标做出了更一般、更迅速的陈述:
func process<T>(_ arr: [T],
filtering filterPred: ((T)->Bool)? = nil,
processing processPred: ((T)->Void)) {
// ...
}
非常好!但是我们忽略了处理过滤函数。让我们来解决这个问题。显然,这是橡胶与道路的交汇点。同样清楚的是,这是一个要传递到过滤器中的函数。但是,我们只能在它不是nil
的情况下通过展开来实现这一点。如果是nil
,该怎么办?OP已经指定,在这种情况下,我们应该让所有元素通过过滤器
请考虑一个谓词函数,它将被传递到<代码>筛选器< /代码>。什么是让一切通过的功能?它是:
{ _ in true }
这就是在nil凝聚算子之后要做的!因此,这是完整的答案:
func process<T>(_ arr: [T],
filtering filterPred: ((T)->Bool)? = nil,
processing processPred: ((T)->Void)) {
arr.filter(filterPred ?? { _ in true }).forEach(processPred)
}
谁说我想要一个包含过滤器,而不是前缀匹配?还是正则表达式过滤器?这似乎是一个错误的责任<代码>过程
应该关注//对项目做些什么
。如果用户想要过滤输入,他们可以简单地处理(items:input.filter{$0.contains(“foo”))
他们自己。我对你的帖子进行了澄清,但我没有否决任何人。请不要认为是我否定。@LukeSideWalker我们的回答不太正确good@aaronstacy我只是碰巧自己又遇到了这个问题。我现在真的理解了这个问题,瓦卡瓦马的回答很有道理。该说谁呢我想要一个包含
过滤器,而不是前缀匹配?或正则表达式过滤器?这似乎是一个错误的责任。过程
应该关注//对项做些什么
。如果用户想要过滤输入,他们可以简单地处理(items:input.filter{$0.contains(“foo”})
他们自己。我对你的帖子进行了澄清,但我没有否决任何人。请不要认为是我否定。@LukeSideWalker我们的回答不太正确good@aaronstacy我只是碰巧自己又遇到了这个问题。我现在真的理解了这个问题,瓦卡瓦马的回答很有道理。