2017-09-13 23 views
0

我正在从书中快速学习,并且遇到了一个我不知道如何解决的挑战。用hasSuffix返回一个元组

以下是挑战:编写一个名为siftBeans(fromGroceryList:)的函数,该函数需要一个购物清单(作为一个字符串数组)并从其他杂货中“筛选出”这些bean。该函数应该有一个参数名为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

你知道如何在'Array'上使用'filter'吗? – Fogmeister

+0

是的,我知道,这是我以另一种方式做到的。 var beans:[String] = [] var otherGroceries:[String] = []允许列表= [“绿豆”,“牛奶”,“黑豆”,“斑豆”,“苹果”] var other: FUNC siftBeans(fromGroceryList:[字符串])在fromGroceryList { 如果i.hasSuffix( “豆”) { beans.append(ⅰ) } 别的 { otherGroceries.append( { 对于i i) } } }(豆类) print(otherGroceries) –

+0

好的,你已经去了。现在我会回答我将如何做到这一点。如果没有你自己去做,我不想回答:D – Fogmeister

回答

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

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) 
} 
+0

“这是你正在寻找的功能”......不,那是你编写功能来完成所要求的功能的方式。有数以百万计的写作方式。 :) – Fogmeister

+0

@Fogmeister肯定有数百万种方法来做同样的事情。我的意思是我将如何实现这个显示某人使用forEach和元组命名。 – Mohammadalijf

0

您还可以Set.substracting结合单filter操作,所以你只需要原来的阵列上调用一次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将摆脱重复的)。

+0

使用设置为减法会丢失数组的顺序。所以代码: result.otherGroceries == [“milk”,“apples”]有时会错误 – Mohammadalijf

+0

我想这只是OP的一个例子,显示了预期的输出,但是你是对的,排序不会被保留下来。 –