Swift中使用数组进行模式匹配的switch语句

12

想知道是否有一种方法可以在Swift中实现以下操作。

let foo = [1, 2, 3]
let bar = [4, 5, 6]

let value = 5

switch value {
case in foo
    print("5 is in foo")
case in bar
    print("5 is in bar")
default:
    break
}

我知道还有其他方法可以让这个人为的例子工作,比如使用case 4, 5, 6:或者不使用switch而是使用bar.contains(value),但是我正在寻找一种特别涉及到将switch模式匹配到一个数组的解决方案。谢谢!

3个回答

31

怎么样:

let foo = [1, 2, 3]
let bar = [4, 5, 6]

let value = 5

switch value {
case _ where foo.contains(value):
    print("\(value) is in foo")
case _ where bar.contains(value):
    print("\(value) is in bar")
default:
    print("\(value) is not in foo or bar")
}

我认为这个解决方案比被接受的答案更容易理解。谢谢! :) - Clifton Labrum
这个答案使用起来比被接受的答案更安全。谢谢。 - Vitalii
@Vitalii,你认为被接受的答案有什么不够“安全”的地方吗? - matt

27
您可以定义一个自定义的模式匹配运算符~=,该运算符以数组作为“模式”并以值作为参数:
func ~=<T : Equatable>(array: [T], value: T) -> Bool {
    return array.contains(value)
}

let foo = [1, 2, 3]
let bar = [4, 5, 6]

let value = 5

switch value {
case foo:
    print("\(value) is in foo")
case bar:
    print("\(value) is in bar")
default:
    break
}

类似的运算符已经存在,例如对于区间:

public func ~=<I : IntervalType>(pattern: I, value: I.Bound) -> Bool

1
不错,真希望我能想到那个。 - Abizern

0

@Martin R 为什么只停留在数组上呢?所有符合Sequence协议的类型都有一个contains实例方法。以下代码与您的答案具有相同的行为,但它适用于符合Sequence的任何类型。

func ~=<S : Sequence>(sequence: S, value: S.Element) -> Bool
        where S.Element: Equatable {

    return sequence.contains(value)
}


let items = [1, 2, 3, 4, 5]
let iterable = items.makeIterator()

let value = 3

switch value {
    case iterable:
        print("\(value) is contained in iterable")
    default:
        print("\(value) is NOT contained in iterable")
}

然而,我们可以做得更好

我认为case iterable太神奇了。它没有传达我们正在测试valueiterable中的成员身份这一事实。如果我们能写case containedIn(iterable)会更好。实际上,这是可能的:

public func ~=<T>(pattern: (T) -> Bool, value: T) -> Bool {
    return pattern(value)
}

func containedIn<S : Sequence>(_ sequence: S) -> ((S.Element) -> Bool)
        where S.Element: Equatable {

    return { element in sequence.contains(element) }
}

let arrayOfNumbers = [1, 2, 3, 4, 5]
let setOfNumbers: Set = [5, 6, 7, 8, 9, 10]

let value = 8

switch value {
    case containedIn(arrayOfNumbers):
        print("\(value) is contained in arrayOfNumbers")
    case containedIn(setOfNumbers):
        print("\(value) is contained in setOfNumbers")
    default:
        break
}

唯一的问题是,当在 switch 语句的上下文之外使用 containedIn 时,它的行为会出现意外情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接