Last active
April 3, 2019 09:42
-
-
Save hwj0623/0d08bc3a97d4e28c86617da8607ffa87 to your computer and use it in GitHub Desktop.
04/02 pair programming of UnitConverter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// main.swift | |
// UnitConverter | |
// | |
// Created by Doran & Dominic on 02/04/2019. | |
// Copyright © 2019 hw. All rights reserved. | |
import Foundation | |
// 소숫점 n자리에서 반올림 extension | |
extension Double { | |
func rounded(toPlace places: Int)-> Double { | |
let divisor = pow(10.0, Double(places)) | |
return (self * divisor).rounded()/divisor | |
} | |
} | |
// 2-4 | |
// 18cm 등 수치와 단위가 혼재된 단어에 대한 정규식 | |
// "128cm" -> [ "128", "cm"] | |
extension String { | |
func unitSeperate() -> [String] { | |
var unit: [String] = [] | |
var number: [String] = [] | |
if let regex = try? NSRegularExpression(pattern: "[a-zA-Z]+$", options: .caseInsensitive) | |
{ | |
let string = self as NSString | |
unit = regex.matches( | |
in: self, | |
options: [], | |
range: NSRange(location: 0, length: string.length) | |
) | |
.map { | |
string.substring(with: $0.range) | |
} | |
} | |
if let regex = try? NSRegularExpression(pattern: "^[^a-zA-Z]*", options: .caseInsensitive) | |
{ | |
let string = self as NSString | |
number = regex.matches( | |
in: self, | |
options: [], | |
range: NSRange(location: 0, length: string.length) | |
) | |
.map { | |
string.substring(with: $0.range) | |
} | |
} | |
if unit.count != 0 && number.count != 0 { | |
number.append(unit[0]) | |
return number | |
}else{ | |
return [] | |
} | |
} | |
} | |
//// - 소숫점 처리를 위해 extension 활용. 넷째 자리에서 반올림 | |
// 2-2 FUNCTION : 1 cm -> 0.01 m | |
func convertCmToM (cmToM: String) -> String { | |
let doubleValue : Double = NSString(string: cmToM as NSString).doubleValue | |
let divisor: Double = 100 | |
let result = Double(doubleValue/divisor).rounded(toPlace: 4) | |
print ("\(cmToM)cm -> \(result)m") | |
return String(result) | |
} | |
// 2-2 FUNCTION : 1 cm -> 0.393701 inch | |
func convertCmToInch (cmToInch: String) -> String { | |
let doubleValue : Double = NSString(string: cmToInch as NSString).doubleValue | |
let divisor: Double = 2.54 | |
let result = Double(doubleValue / divisor).rounded(toPlace: 4) | |
print ("\(cmToInch)cm -> \(result)Inch") | |
return String(result) | |
} | |
// 2-2 FUNCTION : 1 m -> 100 cm | |
func convertMToCm (mToCm: String ) -> String { | |
let doubleValue : Double = NSString(string: mToCm as NSString).doubleValue | |
let times: Double = 100 | |
let result = Double(doubleValue * times).rounded(toPlace: 4) | |
print ("\(mToCm)meter -> \(result)cm") | |
return String(result) | |
} | |
// 2-2 FUNCTION : 1 inch -> 2.54 cm | |
func convertInchToCm (inchToCm: String) -> String { | |
let doubleValue : Double = NSString(string: inchToCm as NSString).doubleValue | |
let times: Double = 2.54 | |
let result = Double(doubleValue * times).rounded(toPlace: 4) | |
print ("\(inchToCm)inch -> \(result)cm") | |
return String(result) | |
} | |
// 2-5 | |
// yard --> 다른 단위로 환산 | |
// 1 yard -> 91.44 cm | |
func convertYardToCm(yardToCm: String ) -> String{ | |
let doubleValue : Double = NSString(string: yardToCm as NSString).doubleValue | |
let times: Double = 91.44 | |
let result = Double(doubleValue * times).rounded(toPlace: 4) | |
print ("\(yardToCm) yard -> \(result) cm") | |
return String(result) | |
} | |
// 1 yard -> 36 inch | |
func convertYardToInch (yardToInch: String )-> String{ | |
let doubleValue : Double = NSString(string: yardToInch as NSString).doubleValue | |
let times: Double = 36 | |
let result = Double(doubleValue * times).rounded(toPlace: 4) | |
print ("\(yardToInch) yard -> \(result) inch ") | |
return String(result) | |
} | |
// 다른 단위 -- > yard로 환산 | |
// 1 cm -> 0.0109361 yard | |
func convertCmToYard(cmToYard: String ) -> String { | |
let doubleValue : Double = NSString(string: cmToYard as NSString).doubleValue | |
let divisor: Double = 91.44 | |
let result = Double(doubleValue / divisor).rounded(toPlace: 4) | |
print ("\(cmToYard) cm -> \(result) yard") | |
return String(result) | |
} | |
// 1 inch -> 0.0277778 yard | |
func convertInchToYard(inchToYard: String )-> String{ | |
let doubleValue : Double = NSString(string: inchToYard as NSString).doubleValue | |
let times: Double = 36 | |
let result = Double(doubleValue * times).rounded(toPlace: 4) | |
print ("\(inchToYard) inch -> \(result) yard ") | |
return String(result) | |
} | |
// 2-2 FUNCTION : unitConverter | |
// 2-4 FUNCTION : unitConverter overloading | |
func unitConverter (number: String, input: String) -> Void { | |
// Grab the last two or one characters | |
switch input { | |
case "cm" : | |
_ = convertCmToM(cmToM: number) | |
case "m" : | |
_ = convertMToCm(mToCm: number) | |
case "inch" : | |
_ = convertInchToCm(inchToCm: number) | |
case "yard" : | |
let bypass = convertYardToCm(yardToCm: number) | |
_ = convertCmToM(cmToM: bypass) | |
default : | |
print("지원하지 않는 단위입니다.") | |
} | |
} | |
// FUNCTION : FROM -> TO 로 파라미터가 주어진 경우에 대한 오버로딩 함수 | |
func unitConverter(number: String, from: String, to : String) -> Void { | |
switch from { | |
case "cm": | |
fromCmToWhat(number: number, to: to) | |
case "m": | |
fromMToWhat(number: number, to: to) | |
case "inch": | |
fromInchToWhat(number: number, to: to) | |
case "yard": | |
fromYardToWhat(number: number, to: to) | |
default : | |
print("지원하지 않는 단위입니다.") | |
} | |
} | |
// FUNCTION : cm 에서 변환할 수치와 단위를 나타내는 서브루틴 함수 | |
func fromCmToWhat (number: String, to: String) -> Void{ | |
switch to { | |
case "m": | |
_ = convertCmToM(cmToM: number) | |
case "inch": | |
_ = convertCmToInch(cmToInch: number) | |
case "yard": | |
_ = convertCmToYard(cmToYard: number) | |
default: | |
print("지원하지 않는 단위입니다.") | |
} | |
} | |
// FUNCTION : m 에서 변환할 수치와 단위를 나타내는 서브루틴 함수 | |
func fromMToWhat (number: String, to: String )-> Void { | |
switch to { | |
case "cm": | |
_ = convertMToCm(mToCm: number) | |
case "inch": | |
let bypass = convertMToCm(mToCm: number) | |
_ = convertCmToInch(cmToInch: bypass) | |
case "yard": | |
let bypass = convertMToCm(mToCm: number) | |
_ = convertCmToYard(cmToYard: bypass) | |
default: | |
print("지원하지 않는 단위입니다.") | |
} | |
} | |
// FUNCTION : inch 에서 변환할 수치와 단위를 나타내는 서브루틴 함수 | |
func fromInchToWhat (number: String, to: String) -> Void { | |
switch to { | |
case "cm": | |
_ = convertInchToCm(inchToCm: number) | |
case "m": | |
let bypass = convertInchToCm(inchToCm: number) | |
_ = convertCmToM(cmToM: bypass) | |
case "yard": | |
_ = convertInchToYard(inchToYard: number) | |
default: | |
print("지원하지 않는 단위입니다.") | |
} | |
} | |
// 2-5 | |
// FUNCTION : yard 에서 변환할 수치와 단위를 나타내는 서브루틴 함수 | |
func fromYardToWhat(number: String, to: String) -> Void { | |
switch to { | |
case "cm": | |
_ = convertYardToCm(yardToCm: number) | |
case "m": | |
let bypass = convertYardToCm(yardToCm: number) | |
_ = convertCmToM(cmToM: bypass) | |
case "inch": | |
_ = convertYardToInch(yardToInch: number) | |
default: | |
print("지원하지 않는 단위입니다.") | |
} | |
} | |
// RUN | |
//2-3 STEP - 값 입력 | |
while true { | |
let str = readLine() | |
// 2-5 종료조건인 경우 탈출 | |
if(str == "quit" || str == "q"){ | |
break | |
} | |
// unit converter process 시작 | |
if let test = str { | |
let firstIdx = test.firstIndex(of: " ") ?? test.endIndex | |
let tmpStr = String(test[..<firstIdx]) | |
let strArr = tmpStr.unitSeperate() | |
let unitIndex = strArr.endIndex-1 | |
let numberIndex = strArr.startIndex | |
//규격에 안맞으면 처음부터 다시 | |
if strArr[unitIndex].lowercased() != "cm" | |
&& strArr[unitIndex].lowercased() != "m" | |
&& strArr[unitIndex].lowercased() != "inch" | |
&& strArr[unitIndex].lowercased() != "yard" | |
{ | |
print("지원하지 않는 단위입니다.") | |
continue | |
} | |
//2 input elements | |
if(firstIdx != test.endIndex){ | |
let secondStr = test.split(separator: " ", omittingEmptySubsequences: true)[1] | |
unitConverter(number: strArr[numberIndex], from: strArr[unitIndex], to: String(secondStr)) | |
} | |
//1 input element | |
else{ | |
unitConverter(number: strArr[numberIndex], input: strArr[unitIndex]) | |
} | |
} | |
} | |
unitConverter() 부터 하위 변환 fromYardToWhat()
함수들까지도 switch 비교 구문이 많습니다.
모든 타입, 단위가 추가되거나 변경될 때마다 비교 구문을 수정해야만 합니다.
비교 구문을 사용하지 않고 함수를 조금이라도 줄일 수 있는 방법은 없을지 고민해보세요 :)
넵 리뷰 감사합니다.
어제 스위프트 정규식과 숫자/문자 변환 이슈에 치중하다보니 구조적인 부분에 대한 고민이 좀 적었네요
리팩토링해보겠습니다.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
오 extension도 있고, 정규표현식도 있네요!
let doubleValue : Double = NSString(string: inchToCm as NSString).doubleValue
동일하게 반복되는데 매개변수 자체를 Double 타입으로 하는게 나았던 게 아닐까요?let times: Double = 2.54
동일한 상수를 쓴다면 공통 상수로 선언하는게 좋을 것 같습니다.while true
반복문 내부도 역할에 따라서 함수를 분리해보면 더 깔끔하게 정리가 될 것 같습니다.