Как использовать Closure для переработки кода в Swift? - PullRequest
0 голосов
/ 07 октября 2019

Я хотел бы использовать Closures (или, возможно, какой-то другой метод) для устранения повторяющегося кода в Swift.

Вот (упрощенная версия) того, что у меня есть:

hasAboveThreshold

func hasAboveThreshold(data: [Double], threshold: Double) -> Bool {
    for i in 0..<data.count {
        if data[i] > threshold {
            return true
        }
    }
    return false
}

hasBetweenThreshold

func hasBetweenThreshold(data: [Double], threshold1: Double, threshold2: Double) -> Bool {
    for i in 0..<data.count {
        if threshold2 > data[i] && data[i] > threshold1 {
            return true
        }
    }
    return false
}

В реальном коде каждая из этих функций имеет длину около 25 строк.

ONLYРазличие в этих двух функциях заключается в условии в выражении if.

Мне кажется, что наличие двух по существу идентичных функций является избыточным, и я хотел бы объединить их в одну функцию, которая принимает замыкание (akaлямбда) как часть его параметров?

Кто-нибудь знает, как этого добиться? Большое спасибо заранее!

Ответы [ 3 ]

1 голос
/ 07 октября 2019

Swift уже предоставляет то, что вы хотите. Используйте метод массива contains(where:).

let numbers = [3.14, 5.7, 1.2, 6.7]

// Your hasAboveThreshold
let threshold = 4.0
let hasAbove = numbers.contains { $0 > threshold }

// Your hasBetweenThreshold
let lower = 2.0
let upper = 6.0
let hasBetween = numbers.contains { $0 > lower && $0 < upper }

print(hasAbove, hasBetween)
1 голос
/ 07 октября 2019

Чтобы расширить уже существующие ответы, функции обеспечивают высокую степень повторного использования, а для вашего конкретного примера могут работать функции высокого порядка.

Начнем с определения основных блоков для сравнения данных. операции, которые вы хотите выполнить:

/// Creates a function that acts as a comparator against the received value
func isGreater<T: Comparable>(than value: T) -> (T) -> Bool {
    return { $0 > value }
}

/// Creates a function that checks if the argument in betwen the two bounds
func isWithin<T: Comparable>(_ lower: T, and upper: T) -> (T) -> Bool {
    return { lower..<upper ~= $0 }
}

/// Creates a function that checks if an array contains elements that satisfy the given predicate
func contains<T>(_ predicate: @escaping (T) -> Bool) -> ([T]) -> Bool {
    return { $0.contains(where: predicate) }
}

Обе вышеперечисленные функции создают и возвращают новую функцию, которую можно сохранить и использовать в любом месте вашего приложения.

Теперь давайте разместим функциидля хорошего использования:

func hasAboveThreshold(threshold: Double) -> ([Double]) -> Bool {
    return contains(isGreater(than: threshold))
}

func hasBetweenThreshold(threshold1: Double, threshold2: Double) -> ([Double]) -> Bool {
    return contains(isWithin(threshold1, and: threshold2))
}

Обратите внимание, как каждый фрагмент (функция) из первого фрагмента кода был повторно использован посредством композиции функций. Таким образом, вы достигаете цели повторного использования.

Пример использования:

let numbers = [1.1, 2.2, 3.3, 4.4, 5.5]
let hasBetween1AndTen = hasBetweenThreshold(threshold1: 1.0, threshold2: 10.0)
print(hasBetween1AndTen(numbers))

Когда вы сохраняете hasBetween1AndTen в переменной, вы можете использовать ее в любое время и в любом месте, гдеимеет доступ к этой переменной.

0 голосов
/ 07 октября 2019

Если вы используете first(where:), в этом действительно нет необходимости

func hasAboveThreshold(data: [Double], threshold: Double) -> Bool {
    return data.first { $0 > threshold }  != nil
}

func hasBetweenThreshold(data: [Double], threshold1: Double, threshold2: Double) -> Bool {
    return data.first { $0 < threshold2 && $0 > threshold1 } != nil
}

Теперь вам вообще не нужны эти функции, и вы можете использовать это непосредственно в своем коде вместо

if let _ = someArray.first(where: { $0 > 3.0 })  {

}

if let _ = someArray.first(where: { $0 < 3.0 && $0 > 2.0) {

}

На самом деле contains как используется @rmaddy - лучший выбор, но ключевой момент заключается в том, что вы можете использовать встроенную функцию и изменить замыкание для нее

...