Potato
์•ˆ๋…•ํ•˜์„ธ์š”, ๊ฐ์žก๋‹ˆ๋‹ค?๐Ÿฅ” ^___^ ๐Ÿ˜บ github ๋ฐ”๋กœ๊ฐ€๊ธฐ ๐Ÿ‘‰๐Ÿป

Swift/Swift Documents

[Swift] ๊ณต์‹ ๋ฌธ์„œ ์ •๋ฆฌ (12) - Subscripts (์„œ๋ธŒ ์Šคํฌ๋ฆฝํŠธ, [])

๊ฐ์ž ๐Ÿฅ” 2022. 2. 25. 23:14
๋ฐ˜์‘ํ˜•

์•ˆ๋…•ํ•˜์„ธ์š”, ๊ฐ์ž์ž…๋‹ˆ๋‹ค. ์˜ค๋Š˜์€ ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด, string์—์„œ ์ธ๋ฑ์Šค๋กœ ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ์‹์— ๋Œ€ํ•ด์„œ๋„ ๋‚˜์˜ค๋Š”๋ฐ์š”, ์ด ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ๋„ ํŒŒ์ด์ฌ์—์„œ๋Š” ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋˜๋Š”๋ฐ, ์™œ ์•ˆ๋ผ!!! ํ•˜๋ฉด์„œ ์„ฑ์งˆ๋ƒˆ๋˜ ๊ธฐ์–ต์ด ์žˆ๋„ค์š” ํ—ˆํ—ˆ... ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋ฌธ์ž์—ด์—์„œ๋„ [index]๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค! ๊ทธ๋Ÿผ ์ด์ œ ์‚ดํŽด๋ณด๋„๋ก ํ•˜์ฃ .

Swift Documents chap.12 Subscripts ๋ฐ”๋กœ๊ฐ€๊ธฐ

 

Subscripts — The Swift Programming Language (Swift 5.6)

Subscripts Classes, structures, and enumerations can define subscripts, which are shortcuts for accessing the member elements of a collection, list, or sequence. You use subscripts to set and retrieve values by index without needing separate methods for se

docs.swift.org


 

Subscripts๋ž€?

ํด๋ž˜์Šค, ๊ตฌ์กฐ์ฒด, ๊ทธ๋ฆฌ๊ณ  ์—ด๊ฑฐํ˜•์—์„œ ์‹œํ€€์Šค์˜ ๋ฉค๋ฒ„ ์š”์†Œ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ๋ฐ”๋กœ๊ฐ€๊ธฐ ์ฒจ์ž๋กœ, ๋‹จ์ผ ํƒ€์ž…์— ์—ฌ๋Ÿฌ ์„œ๋ธŒ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ด์šฉํ•˜๋ฉด ์ถ”๊ฐ€์ ์ธ ๋ฉ”์„œ๋“œ ์—†์ด ํŠน์ • ๊ฐ’์„ ํ• ๋‹นํ•˜๊ฑฐ๋‚˜ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ํ‰์†Œ์— ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž์ฃผ ์‚ฌ์šฉํ•ด์™”๋‹ค. ๋ฐฐ์—ด์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” someArray[index]๋กœ, ๋”•์…”๋„ˆ๋ฆฌ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” someDictionary[index]๋กœ [] ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์ด [] ๊ฐ€ ๋ฐ”๋กœ ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ์ด๋‹ค.

๋ฐฐ์—ด index์— ์ ‘๊ทผํ•˜๋Š” []์˜ ์ •์˜๋ฅผ ๋”ฐ๋ผ๊ฐ€๋ณด๋ฉด, ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

@inlinable public subscript(index: Int) -> Element

[]๋Š” ์ด๋ ‡๊ฒŒ ์ •์˜๋˜์–ด ์žˆ๋Š”๋ฐ, ๋ฐฐ์—ด์˜ ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋Š” parameter๋กœ Intํ˜•์„ index๋กœ ๋ฐ›๊ณ , ํ•ด๋‹น index์— ํ•ด๋‹นํ•˜๋Š” Element๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ˜•ํƒœ์ž„์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋Š” ์ด์ฒ˜๋Ÿผ ์‹œํ€€์Šค์˜ ๋ฉค๋ฒ„ ์š”์†Œ์— ์ ‘๊ทผํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.

 

Subscript Syntax (์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ•)

์„œ๋ธŒ ์Šคํฌ๋ฆฝํŠธ ์„ ์–ธ ๋ฌธ๋ฒ•์€ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ์™€ ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ๋ฅผ ์„ ์–ธํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜๋‹ค. ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ์™€ ๋‹ค๋ฅธ ์ ์€, ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋Š” ์ฝ๊ณ -์“ฐ๊ธฐ ํ˜น์€ ์ฝ๊ธฐ ์ „์šฉ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ •์˜๋Š” ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ ๋ฐฉ์‹๊ณผ ๊ฐ™์ด setter, getter ๋ฐฉ์‹์„ ๋”ฐ๋ฅธ๋‹ค.

subscript(index: Int) -> Int {
    get {
        // ์ ์ ˆํ•œ ๋ฐ˜ํ™˜ ๊ฐ’
    }
    set(newValue) {
        // ์ ์ ˆํ•œ set ์•ก์…˜
    }
}

์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ์˜ set์— ๋Œ€ํ•œ ์ธ์ž ๊ฐ’์„ ๋”ฐ๋กœ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด, ๊ธฐ๋ณธ ๊ฐ’์œผ๋กœ newValue๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ์„ ์–ธํ•˜๋ ค๋ฉด, get, set์„ ์ง€์šฐ๊ณ  ๋”ฐ๋กœ ์ง€์ •ํ•˜์ง€ ์•Š๊ณ  ์ž‘์„ฑํ•˜๊ฒŒ ๋˜๋ฉด get์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋˜์„œ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ์„ ์–ธ๋œ๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ๋Š” ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ์„ ์–ธ๋œ ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ์ด๋‹ค.

/*---------์ฝ๊ธฐ ์ „์šฉ ๊ธฐ๋ณธ ํ˜•ํƒœ--------*/
subscript(index: Int) -> Int {
    // ์ ์ ˆํ•œ ๋ฐ˜ํ™˜ ๊ฐ’
}

struct TimesTable {
    let multiplier: Int
    subscript(index: Int) -> Int {
        return multiplier * index
    }
}
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \\(threeTimesTable[6])")
// "six times three is 18" ์ถœ๋ ฅ

โ–ท ์ฝ”๋“œ ์„ค๋ช…

  • TimeTable ๊ตฌ์กฐ์ฒด์˜ multiplier๋ฅผ 3์œผ๋กœ ์„ค์ •ํ•˜๊ณ  threeTimesTable[6]์—์„œ 6๋ฒˆ์งธ ๊ฐ’, ์—ฌ๊ธฐ์„œ๋Š” 3์— 6์„ ๊ณฑํ•œ๊ฐ’์„ ์ถœ๋ ฅํ•จ.

 

Subscript Usage (์„œ๋ธŒ์ŠคํŠธ๋ฆฝํŠธ ์‚ฌ์šฉํ•˜๊ธฐ)

์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ ์‚ฌ์šฉ ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณด์ž.

var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2

numberOfLegs ๊ฐ’์€ ํƒ€์ž… ์ถ”๋ก ์— ์˜ํ•ด [String: Int]ํ˜•์„ ๊ฐ–๋Š”๋‹ค. numberOfLegs[”bird”] = 2 ๋Š” ์‚ฌ์ „ํ˜• ๋ณ€์ˆ˜ numberOfLegs ์— key๋กœ bird๋ฅผ , ๊ทธ ๊ฐ’์€ 2๋ฅผ ๋„ฃ์œผ๋ ค๋Š” ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ•์ด๋‹ค.

โ–ท note

  • ๋”•์…”๋„ˆ๋ฆฌ์˜ ๋ฐ˜ํ™˜๊ฐ’์€ optional์ด๋‹ค. ์‚ฌ์ „์— ํŠน์ • ํ‚ค ๊ฐ’์ด ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ ์‚ฌ์šฉํ•˜๊ธฐ (1)

let name = "jisoo"
name[0]  //ERROR

name[0]์„ ํ•˜๋ฉด ์ œ์ผ ์•ž์—์žˆ๋Š” ์•ŒํŒŒ๋ฒณ “j”๊ฐ€ ๋ฐ˜ํ™˜๋˜๋ฉด ์ข‹๊ฒ ์ง€๋งŒ, ์ด๋Š” ์—๋Ÿฌ์ด๋‹ค. ํ•ด๋‹น ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒƒ์ด๋‹ค. ์šฐ๋ฆฌ๋Š” ์ด์ œ ๊ฐ’์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ์œผ๋‹ˆ, ์ด๋ ‡๊ฒŒ ์ธ๋ฑ์Šค๋กœ ์•ŒํŒŒ๋ฒณ์— ์ ‘๊ทผํ•˜๋Š” ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งŒ๋“ค์–ด๋ณด์ž.

extension String {
	subscript(idx: Int) -> String? {
		guard(0..<count).conrtains(idx) else {
				return nil
		}
		let target = index(startIndex, offsetBy: idx)
		return String(self[target])
	}
}

์ด๋ ‡๊ฒŒ String์„ ํ™•์žฅํ•˜์—ฌ ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ง์ ‘๊ตฌํ˜„ํ•ด์ฃผ๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ String์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

let name = "jisoo"
name[0]  //optional("j")
name[100]  //nil 

 

์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ ์‚ฌ์šฉํ•˜๊ธฐ (2)

struct Stack {
	var stack: [Int] = [0,1,2,3,4,5]

	subscript(index: Int) -> Int {
		get {
			return stack[index]
		}
		set {
			stack[index] = newValue
		}
	}
}

/*---------- []๋ฅผ ํ†ตํ•ด getter, setter์— ์ ‘๊ทผํ•˜๊ธฐ ------------*/
var stack: Stack = .init()
stack[0]   // ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ getter์— ์ ‘๊ทผ
stack[1] = 2   // ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ setter ์— ์ ‘๊ทผ

 

Subscript Options

์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋Š” ์ž…๋ ฅ ์ธ์ž์˜ ์ˆซ์ž์— ์ œํ•œ์ด ์—†๊ณ , ์ž…๋ ฅ ์ธ์ž์˜ ํƒ€์ž…๊ณผ ๋ฐ˜ํ™˜ํƒ€์ž…์˜ ์ œํ•œ๋„ ์—†๋‹ค. ๋‹ค๋งŒ in-out ํŒŒ๋ผ๋ฏธํ„ฐ๋‚˜ ๊ธฐ๋ณธ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ์ œ๊ณตํ•  ์ˆ˜๋Š” ์—†๋‹ค. ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋Š” ์˜ค๋ฒ„๋กœ๋”ฉ๋„ ํ—ˆ์šฉํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์ธ์žํ˜•, ๋ฐ˜ํ™˜ํ˜•์— ๋”ฐ๋ผ ์›ํ•˜๋Š” ์ˆ˜ ๋งŒํผ์˜ ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‹ค์Œ์€ ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋‹ค์ฐจ์› ํ–‰๋ ฌ์„ ์„ ์–ธํ•˜๊ณ  ์ ‘๊ทผํ•˜๋Š” ์˜ˆ์‹œ์ด๋‹ค.

struct Matrix {
    let rows: Int, columns: Int
    var grid: [Double]
    init(rows: Int, columns: Int) {
        self.rows = rows
        self.columns = columns
        grid = Array(repeating: 0.0, count: rows * columns)
    }
    func indexIsValid(row: Int, column: Int) -> Bool {
        return row >= 0 && row < rows && column >= 0 && column < columns
    }
    subscript(row: Int, column: Int) -> Double {
        get {
            assert(indexIsValid(row: row, column: column), "Index out of range")
            return grid[(row * columns) + column]
        }
        set {
            assert(indexIsValid(row: row, column: column), "Index out of range")
            grid[(row * columns) + column] = newValue
        }
    }
}

์œ„ ์ฝ”๋“œ์—์„œ subscript(row: Int, column: Int) -> Double ์ฝ”๋“œ์™€ ๊ฐ™์ด row, column 2๊ฐœ์˜ ์ธ์ž๋ฅผ ๋ฐ›๊ณ , Double์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์„ ์–ธํ–ˆ๋‹ค. get, set ๊ฐ๊ฐ์— indexIsValid๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์œ ์š”ํ•œ ์ธ๋ฑ์Šค๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ ํ”„๋กœ๊ทธ๋žจ์ด ๋ฐ”๋กœ ์ข…๋ฃŒ๋˜๋„๋ก assert๋ฅผ ํ˜ธ์ถœํ–ˆ๋‹ค. ์„ ์–ธํ•œ ์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ•์„ ์ด์šฉํ•ด var matrix = Matrix(rows: 2, columns: 2) 2 by 2 ํ–‰๋ ฌ์„ ์„ ์–ธํ•œ๋‹ค.

grid ๋ฐฐ์—ด์€ ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ์— ์˜ํ•ด ์œ„์™€ ๊ฐ™์ด row์™€ column์„ ๊ฐ–๋Š” ํ–‰๋ ฌ๋„ ๋™์ž‘ํ•œ๋‹ค. ํ–‰๋ ฌ์— ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ด์šฉํ•ด ํŠน์ • row, column์— ๊ฐ’์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค.

matrix[0, 1] = 1.5
matrix[1, 0] = 3.2

๊ฐ’์„ ๋„ฃ์€ ๊ฒฐ๊ณผ ํ–‰๋ ฌ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

ํ–‰๋ ฌ์˜ ์ž…์ถœ๋ ฅ์‹œ row๋‚˜ column์˜ ๋ฒ”์œ„๊ฐ€ ์ ์ ˆํ•œ์ง€ ์•„๋ž˜์˜ ์ฝ”๋“œ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

func indexIsValid(row: Int, column: Int) -> Bool {
    return row >= 0 && row < rows && column >= 0 && column < columns
}

๋งŒ์•ฝ ์ ์ ˆํ•œ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด assert๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

let someValue = matrix[2, 2]
// [2, 2]๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ–‰๋ ฌ์˜ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜๋ฏ€๋กœ assert๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

 

๋ฐ˜์‘ํ˜•