我从一本书中学得很快,我遇到了一个我不知道如何解决的挑战。
以下是挑战:编写一个名为siftBeans(fromGroceryList:)
的函数,它将一个购物清单(作为字符串数组)和“筛选出”来自其他杂货的咖啡豆。该函数应该采用一个名为list的参数名称的参数,并且它应该返回一个(beans: [String], otherGroceries: [String])
类型的命名元组。
以下是您应该如何调用函数以及结果应该是什么的示例:
let result = siftBeans(fromGroceryList: ["green beans",
"milk",
"black beans",
"pinto beans",
"apples"])
result.beans == ["green beans", "black beans", "pinto beans"] // true
result.otherGroceries == ["milk", "apples"] // true
提示:您可能需要在名为hasSuffix(_:)的String类型上使用函数。
答案 0 :(得分:1)
这就是我写函数的方法。
func siftBeans(groceries: [String]) -> (beans: [String], otherGroceries: [String]) {
return (
groceries.filter { $0.hasSuffix("beans") },
groceries.filter { !$0.hasSuffix("beans") }
)
}
过滤器功能使用hasSuffix
来确定是否应包含项目。所以我只运行两次,一次获取所有...beans
项,一次获得其余项目。
它会对数组进行两次迭代,但这不是什么大问题。我实际上有一个函数在一个数组上执行filterInOut
,为任何数组执行此操作。
修改强>
我想改进这一点,看看我是否能提供更好的通用替代方案。
所以我提出了这个......
extension Collection {
func separated(_ divisor: (Iterator.Element) -> (Bool)) -> (in: [Iterator.Element], out: [Iterator.Element]) {
return reduce((in: [], out: [])) {
divisor($1) ? ($0.in + [$1], $0.out) : ($0.in, $0.out + [$1])
}
}
}
它是Collection
的扩展名,因此可用于任何类型的集合。它需要一个返回Bool
的闭包。结果是一个元组(in: [], out: [])
,它使用闭包来以任何方式过滤项目。
它可以像这样使用......
let array = [1, 2, 3, 4, 5, 6, 7, 8]
array.separated { $0 % 2 == 0 } // ([2, 4, 6, 8], [1, 3, 5, 7])
或者,在您的用例中......
let array = ["green beans", "milk", "black beans", "pinto beans", "apples"]
array.separated { $0.hasSuffix("beans") } // (["green beans", "black beans", "pinto beans"], ["milk", "apples"])
希望有所帮助:D
答案 1 :(得分:0)
元组项可以具有类似函数参数的名称。这是你正在寻找的功能
func siftBeans(from groceryList: [String]) -> (beans: [String], otherGroceries: [String]) {
var beans = [String]()
var otherGroceries = [String]()
groceryList.forEach { (grocery) in
grocery.hasSuffix("beans") ? beans.append(grocery) : otherGroceries.append(grocery)
}
return (beans , otherGroceries)
}
答案 2 :(得分:0)
您还可以将单个Set.substracting
操作与filter
结合使用,这样您只需要在原始数组上调用func filterBeans(groceryList: [String])->(beans: [String], otherGroceries: [String]){
let beans = groceryList.filter({$0.hasSuffix("beans")})
let otherGroceries = Array(Set(groceryList).subtracting(beans))
return (beans, otherGroceries)
}
一次而不是调用它两次(对于具有后缀的元素,只需调用一次)并且一旦没有它的元素。)
groceryList
当然,为了实现这一点,输入Set
只需要具有唯一元素(否则创建中间{{1}}将删除重复项。)