1

I'm trying to evaluate if an entered string partially matches any item in an array. When I use the following method in playgrounds it seems to work properly. However, when I use the exact same method in Xcode 9.0 beta 6 (9M214v) it doesn't return the correct answer.

func isValid(_ item: String)  -> Bool {
    let whitelist = ["https://apple.com","https://facebook.com","https://stackoverflow.com"]

    return whitelist.contains(where: {$0 <= item ? true : false  })
}

There's also anomalies like when I passed in "https://twitter.com" it'll return true. Am I nuts? And while I'm here, anyone have a different approach to solve this problem?

4
  • 3
    $0 <= item what does that mean ? Commented Sep 12, 2017 at 6:28
  • As @MikeAlter commented, what's the logic of comparing like $0 <= item? Commented Sep 12, 2017 at 6:32
  • You state it works in playgrounds. Which version? Do you actually mean this works in Swift 3 but not Swift 4? Please clarify. Commented Sep 12, 2017 at 6:50
  • @rmaddy swift 4 playgrounds. When I said it worked, my expectations and understanding of what happening in my playground was incorrect. Commented Sep 12, 2017 at 7:15

2 Answers 2

3

theres also anomalies like when I passed in "https://twitter.com" it'll return true.

Whether the version of Swift is 3 or 4, based on your code snippet you should get the same true result! Why?

because the logic of contains(where:) of doing the comparison is related to the logic of the equality of the given elements, i,e you cannot use contains with array of non-equatable elements. To make it more clear:

"https://apple.com" <= "https://twitter.com"
"https://facebook.com" <= "https://twitter.com"
"https://stackoverflow.com" <= "https://twitter.com"

the result would be true for all statements ('t' character is greater than 'a', 'f' and 's').

Thus:

"https://zwebsite" <= "https://twitter.com"

would returns false ('t' is less than 'z').

However, to get the expected result, you could implement your function like this:

func isValid(_ item: String)  -> Bool {

    let whitelist = ["https://apple.com","https://facebook.com","https://stackoverflow.com"]

    return whitelist.contains { $0 == item }
}

Or for even a shorter contains:

return whitelist.contains(item)

Which leads to let

isValid("https://twitter.com")

to returns false.

Sign up to request clarification or add additional context in comments.

3 Comments

It should check the next character in the string, like the case of "https://", until reaching the last element (character), if all matched then it will be an equality.
So what's happening is that its evaluating whether each character is < = the character in the same position. I was under the impression that it was evaluating each item as a one string rather than an array of characters. What I'm trying to do is see if the scheme & host of particular URL matches one in the array. using only contains won't account for the rest of the URL and will return false even it the first part is in the array.
Well, that would be completely another case :) you should work with URL and URLComponenets to achieve it, I could update my answer, but it will be unrelated to the title of your question...
0

Just return the following, which will return true or false:

return whitelist.contains(item)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.