2017-09-13 21 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的一個例子,顯示了預期的輸出,但是你是對的,排序不會被保留下來。 –