Filter and sort swift array

2019-04-04 18:39发布

I have a swift array which I want to filter, here is the array

let array = [apple,workshops,shopping,sports,parties,pantry,pen] 

I want to filter the array in such a way that the items beginning with the search string to appear before items that just contain the search string

So when i search for example p, then the results should be in some way

let array = [parties,pantry,pen,apple,workshops,shopping,sports] 

I tried this

tagSearchResults = tagSearchResults.filter({ (interestTag:InterestTag) -> Bool in
            let tmp: NSString = interestTag.tag
            let range = tmp.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
            return range.location != NSNotFound
        })

but this gives me all strings containing the search string.

So guys how can i do this

3条回答
ゆ 、 Hurt°
2楼-- · 2019-04-04 18:55

Try this. Firstly, it filters the array to remove those elements that do not contain the search string, then uses a custom sort to prefer items that start with the search string. In general, use the Cartesian approach of splitting a problem into smaller sub-problems, rather than try to solve it all in one step.

let searchString = "p"
let array = ["apple", "workshops", "shopping", "sports", "parties", "pantry", "pen", "xyzzy"]

let filteredArray = array.filter({ $0.contains(searchString) })
filteredArray // drops xyzzy

let sortedArray = filteredArray.sorted(isOrderedBefore:  {
    switch ($0.hasPrefix(searchString), $1.hasPrefix(searchString)) {
    case (true, true):
        return $0 < $1
    case (true, false):
        return true
    case (false, true):
        return false
    case (false, false):
        return $0 < $1
    }

})
sortedArray // "pantry", "parties", "pen", "apple", "shopping", "sports", "workshops"] as required
查看更多
我命由我不由天
3楼-- · 2019-04-04 18:55

Another way:

let searchString = "p"
let array = ["apple", "workshops", "shopping", "sports", "parties", "pantry", "pen", "xyzzy"]
let result = array.filter{$0.containsString(searchString)}
    .map{($0.hasPrefix(searchString) ? 0 : 1, $0)}
    .sort{$0 < $1}
    .map{$1}
print(result) //->["pantry", "parties", "pen", "apple", "shopping", "sports", "workshops"]

(I don't know why, but my Xcode took huge time to compile these lines. Believe this compiles and runs as expected eventually.)

查看更多
做个烂人
4楼-- · 2019-04-04 19:02

You can just write

 let result = words
    .filter { $0.contains(keyword) }
    .sorted { ($0.hasPrefix(keyword) ? 0 : 1) < ($1.hasPrefix(keyword) ? 0 : 1) }

Example

let words = ["apple", "workshops", "shopping", "sports", "parties", "pantry", "pen", "cat", "house"]
let keyword = "p"
let result = words
    .filter { $0.contains(keyword) }
    .sorted { ($0.hasPrefix(keyword) ? 0 : 1) < ($1.hasPrefix(keyword) ? 0 : 1) }

// ["pen", "pantry", "parties", "apple", "workshops", "shopping", "sports"]
查看更多
登录 后发表回答