2

I have an enum with a computed property that returns an array of indicies:

enum ScaleDegree {
    case tonic
    case supertonic
    case mediant
    case subdominant
    case dominant
    case submedian
    case leading

    var indexes: [Int] {
        switch self {
        case .tonic: return [0,2,4]
        case .supertonic: return [1,3,5]
        case .mediant: return [2,4,6]
        case .subdominant: return [3,5,0]
        case .dominant: return [4,6,1]
        case .submedian: return [5,0,2]
        case .leading: return [6,1,3]
        }
    }
}

I use this to extract a subarry from a larger array:

let cMajor = ["C", "D", "E", "F", "G", "A", "B"]

let cMajorTonic = [cMajor[ScaleDegree.tonic.indexes[0]], cMajor[ScaleDegree.tonic.indexes[1]], cMajor[ScaleDegree.tonic.indexes[2]]]

The cMajorTonic syntax seems cumbersome and I would expect Swift 4 would give me an easier way to extract individual elements into a new array, but my searching hasn't found a clever way to do this.

Are there any suggestions of a better way to write this?

3
  • 1
    you can also enumerate cMajor and check if your enumeration indexes contains the element offset let cMajorTonic = cMajor.enumerated().flatMap { ScaleDegree.tonic.indexes.contains($0.offset) ? $0.element : nil }. The advantage is that it won't crash your app if your array has less elements than some of your enumeration indexes Commented Dec 23, 2017 at 23:36
  • as a method of your enumeration as suggested by vacawama return scale.enumerated().flatMap{ indexes.contains($0.offset) ? $0.element : nil } Commented Dec 23, 2017 at 23:40
  • fyi, the plural of "index" is "indicies" Commented Dec 24, 2017 at 1:05

1 Answer 1

3

This would be a good place to use map:

let cMajor = ["C", "D", "E", "F", "G", "A", "B"]
let cMajorTonic = ScaleDegree.tonic.indexes.map { cMajor[$0] }
print(cMajorTonic)
["C", "E", "G"]

You could add this function to your enum:

func appliedTo(scale: [String]) -> [String] {
    return self.indexes.map { scale[$0] }
}

And then it would become:

let cMajorTonic = ScaleDegree.tonic.appliedTo(scale: cMajor)
Sign up to request clarification or add additional context in comments.

1 Comment

That represents exactly the kind of way I wanted to write this. Thank you!

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.