【问题标题】:Filter array of array with keyword in Swift在 Swift 中使用关键字过滤数组数组
【发布时间】:2016-06-30 08:22:24
【问题描述】:
let searchResultItem1 = SearchResult()
searchResultItem1.type = "contact"
searchResultItem1.typeTitle = "CONTACTS"
searchResultItem1.results = ["Joe" , "Smith" , "Alan" , "Nick" , "Jason"]

let searchResultItem2 = SearchResult()
searchResultItem2.type = "address"
searchResultItem2.typeTitle = "ADDRESS"
searchResultItem2.results = ["829 6th Street North Fullerton" , "669   Windsor Drive Randallstown" , "423 Front Street Lacey"]
searchResults.append(searchResultItem1)
searchResults.append(searchResultItem2)

当我搜索“al”时,我希望返回一个 SearchResult 及其结果“[Alan]”和另一个 SearchResult 及其结果“[“669 Windsor Drive Randallstown”]”

我尝试了下面的过滤器,但返回空数组。

let results = searchResults.filter({$0.results.contains("al")})

【问题讨论】:

    标签: ios arrays swift filter


    【解决方案1】:

    正如其他两个答案所指出的那样,您正在搜索结果数组以查找值为“al”的项目。你想要的实际上是返回一个结果数组,缩小到只有那些匹配的结果:

    struct SearchResult {
        let type:String
        let typeTitle:String
        let results:[String]
    }
    
    let searchResultItem1 = SearchResult(
        type: "contact",
        typeTitle: "CONTACTS",
        results: ["Joe" , "Smith" , "Alan" , "Nick" , "Jason"]
    )
    
    let searchResultItem2 = SearchResult(
        type:"address",
        typeTitle: "ADDRESS",
        results:["829 6th Street North Fullerton" , "669   Windsor Drive Randallstown" , "423 Front Street Lacey"]
    )
    
    var searchResults = [ searchResultItem1, searchResultItem2 ]
    

    那么,再次为方便起见,为 String 定义一个不区分大小写的 contains 函数:

    extension String {
        func containsIgnoreCase(substring:String) -> Bool {
            return rangeOfString(
                substring,
                options: .CaseInsensitiveSearch,
                range: startIndex..<endIndex,
                locale: nil)?.startIndex != nil
        }
    }
    

    请注意,String 已经有一个contains 函数,它只是区分大小写,但如果这足够了,您甚至不需要定义自己的。

    现在,您可以使用map 删除不包含您的搜索字符串的结果:

    searchResults = searchResults.map({
        return SearchResult(
            type: $0.type,
            typeTitle: $0.typeTitle,
            results: $0.results.filter({
                $0.containsIgnoreCase("al")
            })
        )
    })
    

    而且,大概你还想消除任何没有实际结果的 SearchResult,所以使用过滤器:

    searchResults = searchResults.filter { $0.results.count > 0 }
    

    当然,整件事可以串成一个表达式:

    searchResults = searchResults.map({
        return SearchResult(
            type: $0.type,
            typeTitle: $0.typeTitle,
            results: $0.results.filter({
                $0.contains("al")
            })
        )
    }).filter { $0.results.count > 0 }
    

    而且,您可以通过使用flatMap 进一步减少一些迭代,这类似于map,但消除了任何nil 值:

    searchResults = searchResults.flatMap {
        let results = $0.results.filter { $0.containsIgnoreCase("al") }
        if results.count > 0 {
            return SearchResult(type: $0.type, typeTitle: $0.typeTitle, results: results)
        } else {
            return nil
        }
    }
    

    【讨论】:

      【解决方案2】:

      在您的filter 中,$0.results 在每个示例中都是:

      ["Joe" , "Smith" , "Alan" , "Nick" , "Jason"]
      ["829 6th Street North Fullerton" , "669   Windsor Drive Randallstown" , "423 Front Street Lacey"]
      

      Array.contains(_) 函数搜索与它的参数完全匹配的对象,而不是参数的子字符串

      要获取每个包含带有子字符串“al”的字符串元素的整个数组,请使用:

      let results = searchResults.filter({$0.results.filter({$0.rangeOfString("al") != nil}).count > 0})
      

      或者,要仅获取带有子字符串“al”的字符串,请使用:

      let results = searchResults.map{ $0.results }.reduce([], combine: {$0 + $1}).filter { $0.rangeOfString("al") != nil }
      

      请注意,这不会匹配“Alan”,因为rangeOfString 区分大小写。

      【讨论】:

        【解决方案3】:

        您的过滤器检查结果数组是否包含“al”条目,而不是结果中的任何字符串是否包含“al”。您需要过滤结果数组并使用过滤后的结果数组构造一个新的 SearchResult。

        我可能会平面映射一个函数,该函数过滤输入 SearchResult 的结果数组,并根据是否找到任何匹配项返回一个可选值。

        【讨论】:

        • 你能帮忙解决一下吗?
        • David Berry 最终的代码块是我的想法。
        猜你喜欢
        • 1970-01-01
        • 2019-12-30
        • 2012-02-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多