如何使Swift中的闭包从string中提取两个整数来执行计算

我目前使用Swift中的闭包map属性来从数组中提取线性因子,并计算跨越一个八度的音乐列表。

  let tonic: Double = 261.626 // middle C let factors = [ 1.0, 1.125, 1.25, 1.333, 1.5, 1.625, 1.875] let frequencies = factors.map { $0 * tonic } print(frequencies) // [261.62599999999998, 294.32925, 327.03249999999997, 348.74745799999994, 392.43899999999996, 425.14224999999999, 490.54874999999993] 

我想通过使闭包从一个string中提取两个整数并将它们分成各个因子来实现。 该string来自一个SCL调整文件 ,可能看起来像这样:

  // CDEFGAB let ratios = [ "1/1", "9/8", "5/4", "4/3", "3/2", "27/16", "15/8"] 

可以这样做吗?

谢天谢地,可以。 在三个Swift语句中,调整比率表示为托勒密之前的分数,可以转换为精确的频率。 对接受的答案稍作修改就可以得出频率列表。 这是代码

 import UIKit class ViewController: UIViewController { // Diatonic scale let ratios = [ "1/1", "9/8", "5/4", "4/3", "3/2", "27/16", "15/8"] // Mohajira scale // let ratios = [ "21/20", "9/8", "6/5", "49/40", "4/3", "7/5", "3/2", "8/5", "49/30", "9/5", "11/6", "2/1"] override func viewDidLoad() { super.viewDidLoad() _ = Tuning(ratios: ratios) } } 

调音class

 import UIKit class Tuning { let tonic = 261.626 // frequency of middle C (in Hertz) var ratios = [String]() init(ratios: [String]) { self.ratios = ratios let frequencies = ratios.map { s -> Double in let integers = s.characters.split(separator: "/").map(String.init).map({ Double($0) }) return (integers[0]!/integers[1]!) * tonic } print("// \(frequencies)") } } 

这里是与全音阶音符对应的赫兹频率列表

  CDEFGAB [261.626007, 294.329254, 327.032501, 348.834686, 392.439026, 441.493896, 490.548767] 

它适用于其他音阶,通常在雅克·杜顿创作的黑白音符音乐键盘Mohajira音阶上找不到音调

  // DFGC' let ratios = [ "21/20", "9/8", "6/5", "49/40", "4/3", "7/5", "3/2", "8/5", "49/30", "9/5", "11/6", "2/1"] 

这是一个频率清单

  // DFGC' // [274.70729999999998, 294.32925, 313.95119999999997, 320.49185, 348.83466666666664, 366.27639999999997, 392.43899999999996, 418.60159999999996, 427.32246666666663, 470.92679999999996, 479.64766666666662, 523.25199999999995] 

放弃

目前封闭只处理合理的尺度。 为了完全符合Scala SCL格式,它还必须能够区分具有小数点的string和带有小数点的string,并使用分数(即对数而不是线性因子)来解释后者。

谢谢康康 阿德里安 Atem

 let ratios = [ "1/1", "9/8", "5/4", "4/3", "3/2", "27/16", "15/8"] let factors = ratios.map { s -> Float in let integers = s.characters.split(separator: "/").map(String.init).map({ Float($0) }) return integers[0]!/integers[1]! } 

如果我理解你的问题,你可以这样做:

 func linearFactors(from string: String) -> Double? { let components = string.components(separatedBy: "/").flatMap { Double($0) } if let numerator = components.first, let denominator = components.last { return numerator / denominator } return nil } 

将比率转换为double数组

 let ratios = [ "1/1", "9/8", "5/4", "4/3", "3/2", "27/16", "15/8"] let array = ratios.flatMap { element in let parts = element.components(separatedBy: "/") guard parts.count == 2, let dividend = Double(parts[0]), let divisor = Double(parts[1]), divisor != 0 else { return nil } return parts[0] / parts[1] }