쳇,2020 인 데 왜 아직도 단순히 if-else 를 사용 하 는 거 야?
if-else
와switch-case
와 같은 조건 문 구 를 제공 하여 모두 가 판단 하 는 데 편리 하 다―절차 의 방향 을 인도 한다.우 리 는 프로그램 을 쓸 때 항상 두 가지 또는 더 많은 실행 경 로 를 가리 키 고 프로그램 이 실 행 될 때 그 중의 한 가지 경 로 를 선택 하여 해당 하 는 문 구 를 집행 하여 해당 하 는 결 과 를 만들어 야 한다.이것 도 조건문 이 프로그램 에서 의 역할 이다.if-else 의 예
여러분 은 C 언어 를 처음 배 울 때 이런 프로그램 을 쓴 적 이 있 을 것 입 니 다.출력 매달 일수:
//C
int Days(int months, int years){
int days;
if(months==1 || months==3 || months==5 || months==7 || months==8 || months==10 || months==12){
days=31;
}else if(months==2){
if((years%4==0 && years%100!=0) || years%400==0){
days=29;
}else{
days=28;
}
}else if(months==4 || months==6 || months==9 || months==11){
days=30;
}else{
printf(" ! :
");
Days(months,years);
}
return days;
}
이 프로그램 은 비록'귀 에 익 고 상세 하 다'는 것 이지 만 나중에 보면 약간[번거롭다]는 느낌 을 받 을 수 밖 에 없다.다 층 if-else 의 내장 은 가 독성 을 떨 어 뜨 릴 뿐만 아니 라 프로그램 운행 의 효율 에 도 큰 영향 을 줄 수 있다.질문
위 에서 알 수 있 듯 이 if-else 판단 문 구 는 사용 하기에 매우 간단 하지만 약간 복잡 한 논리 장면 에서 if-else 에 대한 빈번 한 사용(또는 남용)은 전체 프로젝트 의 가 독성 과 유지 가능성 을 크게 낮 출 수 있다.
프로젝트 에 새로운 상황 이 발생 하면 기 존의 코드 를 바탕 으로 if-else 를 계속 추가 해 야 한 다 는 것 을 생각해 볼 수 있 습 니 다.하지만 수 요 는 줄 지 않 을 것 이다.이렇게 악순환 이 계속 되면 원래 의 if-else 몇 개 는 몇 가지 버 전 을 업데이트 한 후에 몇 십 개 로 변 했 을 것 이다.이것 은 정말 웃 을 수 없 는 일이 다.
(물론,지금 당신 의 회사 가 딱딱 한 요 구 를 하거나 템 플 릿 을 개발 할 지도 모 르 니 축하합니다...)
디자인 모델 의 측면 에서 볼 때 if-else 는'나 쁜'코드 가 가 진 모든 것 을 가지 고 있다.
if-else 는 모든 것 을 대체 해 야 하 는 것 이 아니다.정확히 말 하면 우 리 는 지금 그것 을 계속 개선 하여 그 가 더욱 원활 하 게 운행 하도록 할 수 밖 에 없다.
단락 기호 와 삼원 표현 식
며칠 전에 필 자 는 단체 에서 이 두 가 지 를 말 했다.단락 기호 이자'논리 연산 자'라 고도 부 르 는데 간단 한 장면 에서 우 리 는 이 를 통 해 if-else(특히'몇 가지 조건 이 동시에 만족'해 야 하 는 장면 에서)를 대체 할 수 있다.
예 를 들 어 이것―한 수의 옳 고 그 름 을 판단 하 는 멱:
//c++
class Solution {
public:
bool isPowerOfTwo(int n) {
// 2 , 1, 0 ,
// 1 , , 0 1,
// , 0
return (n > 0) && (!(n & (n - 1)));
}
};
우 리 는 또한 3 원 기호 로 if-else 를 대체 할 수 있다.그것 은 거의 가장 적합 한 컴퓨터 판단 기호 이다(필 자 는 스스로 생각한다!).특히 다 조건 복합 판단 에 적합 하 다.그러나 주의해 야 할 것 은 대량의 3 원 연산 자 는 코드 의 가 독성 에 영향 을 주기 쉽다 는 것 이다.판단 n!결과 끝자리 의 0 수량:
//java
public class Solution {
public int trailingZeroes(int n) {
//
return n == 0 ? 0 : n / 5 + trailingZeroes(n / 5);
}
}
물론 우 리 는 또 하나의 개선 방법 이 있다.만약 에 모든 조건 에서 코드 논리 가 비교적 많 으 면 미리 튀 어 나 와 서 끝 내 는 함수 도 고려 할 수 있다.이것 은 for 순환 을 참고 한 것 이다.switch-case 말 해 봐.
switch-case 는 언어 자체 가 제공 하 는 또 다른 조건문 으로 if 와 본질 적 으로 다 를 것 이 없 으 며 코드 만 더욱 간결 해 보일 뿐이다.예 를 들 어 나 이 를 판단 한다.
goodswitch(age){
case 10:
break;
case 20:
break;
case 30:
break;
//...
}
그러나 switch-case 는 여러 가지 비슷 한 조건 에서 여러 번 반복 되 어야 하 는 문 제 를 근본적으로 해결 할 수 없다.표 구동 법
이것 은 필자 가 가장 추앙 하 는 기법 으로 빅 데이터 양 판단,범위 차이 처리 등 문제 에 있어 모두 해결 방안 이 있다!
이제 문장 첫머리 의 그 문 제 를 다시 봅 시다.출력 은 매달 며칠 입 니까?
우 리 는 생각 을 바 꿔 보 자.매달 하나의 숫자 에 대응 하고 달 은 순서대로 배열 되 어 있 기 때문에 우 리 는 하나의 배열 로 일 수 를 저장 한 다음 에 아래 표 시 를 통 해 방문 할 수 있 습 니까?
//javascript
const month=new Date().getMonth(),
year=new Date().getFullYear(),
isLeapYear=year%4==0 && year%100!=0 || year%400==0;
const monthDays=[31,isLeapYear ? 29 : 28,31,30,31,30,31,31,30,31,30,31];
const days=monthDays[month];
아,이 코드 는 실행 하기 가 훨씬 간단 해 요.적어도 이렇게 보 여요.그리고 위 에서 나 이 를 판단 하 는 코드 도 있 습 니 다.우 리 는 이렇게 쓸 수 있 습 니 다.
//JavaScript
ages=[10,20,...];
funs=['a1','a2',...];
for(let i in ages){
if(age==ages[i]){
funs[i]();
}
}
function a1(){
}
function a2(){
}
//...
두 가지 예 를 보 니 너 는[표 구동 법]에 대해 알 게 되 었 을 것 이다.표 구동 법 은 논리 문 구 를 사용 하지 않 고 표 에서 정 보 를 찾 는 프로 그래 밍 모델 이다.사실 논리 문 구 를 통 해 선택 할 수 있 는 모든 것 은 표를 찾 아 선택 할 수 있다.간단 한 경우 에는 논리 문 구 를 사용 하 는 것 이 더 쉽 고 직 설 적 이다.그러나 논리 체인 이 갈수 록 복잡 해 지면 서 차 트 법 도 더욱 매력 적 으로 보인다.코드 대전
시계 구동 을 사용 하 는 것 은 if-else 처럼'가 볍 지 않다'.우 리 는 먼저 두 가지 문 제 를 생각해 야 한다.
어떻게 표 에서 데 이 터 를 조회 합 니까?만약 if-else 가 판단 한 것 이 범위 라면 어떻게 조사해 야 합 니까?뭘 찾 아?데이터색인
이 두 가지 문 제 를 바탕 으로 누군가가 표 에 따라 구동 되 는 조 회 를 세 가지 로 나 누 었 다.
직접 접근 색인 접근 계단 접근
1.직접 방문 표
필 자 는 최근 어머니 의 뜻 에 따라 보험 회 사 를 다 녀 왔 는데 이 보험료 율 이 매우 번 거 로 운 것 을 발견 했다.나이,성별,혼인 상태 등에 따라 달라 질 수 있다.위의 출력 날 짜 를 보 는 프로그램 을 보면 서 논리 적 제어 재 구성(if or switch)으로 서로 다른 비용 율 을 표시 하면 얼마나 번 거 로 울 지 생각해 보 세 요!(사실 당신 의 코드 는 낙지 처럼...)
우 리 는 이곳 의[나이]가 범위 라 는 것 을 알 수 있다!배열 이나 대상 으로 맵 을 만 들 수 없습니다.이것 은 두 가지 해결 방안 이 있 습 니 다.직접 방문 표 or 계단 방문 표 입 니 다.필 자 는 먼저'직접 방문 표'의 방식 을 시험 해 보고 두 가지 방법 을 찾 았 다.
정 보 를 복사 하여 키 값 을 직접 사용 할 수 있 습 니 다.우 리 는 1-17 연령 대의 모든 연령 대 에 정 보 를 복사 한 다음 에 age 로 직접 방문 할 수 있 습 니 다.마찬가지 로 다른 연령 대 에 도 마찬가지 입 니 다.이런 방법 은 조작 이 매우 간단 하고 표 의 구조 도 매우 간단 하 다 는 데 있다.그러나 공간 을 낭비 하 는 단점 이 있다.왜냐하면 많은 불필요 한 정 보 를 만 들 었 기 때문이다.)키 값 을 바 꾸 는 것 을 권장 하지 않 습 니 다.만약 우리 가 연령 범 위 를 키 로 바꾼다 면?이렇게 하면 직접 방문 할 수 있다.유일 하 게 고려 해 야 할 문 제 는 어떤 상황 에서 나이 가 어떻게 키 값 으로 바 뀌 는 지 하 는 것 이다.
두 번 째 방법 에 대해 서 는 if-else 로 전환 해 야 한 다 는 의혹 이 있 을 수 있다.그럼요.앞에서 말 했 듯 이 간단 한 if-else 는 문제 가 없 을 것 이다.표 구동 은 복잡 한 논리 적 판단 을 최적화 시 켜 더욱 유연 하고 확장 하기 쉽다.
//TypeScript
const Age={
0:"unadult",
1:"adult"
}
const Gender={
0:"female",
1:"male"
}
const Marry={
0:"unmarried",
1:"married"
}
const rateMap={
[Age[0]+Gender[0]+Marry[0]]:0.1,
[Age[0]+Gender[0]+Marry[1]]:0.2,
[Age[0]+Gender[1]+Marry[1]]:0.3,
[Age[0]+Gender[1]+Marry[0]]:0.4,
[Age[1]+Gender[0]+Marry[0]]:0.5,
[Age[1]+Gender[0]+Marry[1]]:0.6,
[Age[1]+Gender[1]+Marry[1]]:0.7,
[Age[1]+Gender[1]+Marry[0]]:0.8
}
const isAdult=(age:number)=>age>=18 ? 1: 0
const getDate=(age,hasMarried,gender)=>{
age=isAdult(age)
return rateMap[Age[age]+Gender[gender]+Marry[marry]]
}
그래 야 제대로 열 리 는 거 잖 아!아,맞아요.방금 또 한 가지 방법 을 말 한 것 같 아 요.
2.계단 방문 표
마찬가지 로 위의 연령 대 문 제 를 해결 하기 위해 계단 방문 은 색인 없 이 직접 방문 하지만 공간 을 더욱 절약 할 수 있다.
계단 방법 을 사용 하기 위해 서 는 각 구간 의 상한 선 을 한 장의 표 에 기록 한 후 순환 을 통 해 연령 이 있 는 구간 을 검사 해 야 하기 때문에 계단 을 이용 하여 방문 할 때 구간 의 단점 을 반드시 검사 해 야 한다.
//TypeScript
const ageRanges:number[]=[17,65,100],
keys:string[]=['<18','18-65','>65'];
const getKey=(age:number):string=>{
for(let i in keys){
//console.log(i);
//console.log(ageRanges[i]);
if(age<=ageRanges[i]){
return keys[i];
}
}
return keys[keys.length-1];
}
3.색인 접근 표실제 보험료 율 문 제 는 연령 대 를 처리 할 때 머리 가 아프다.이런 범 위 는 위의 첫 번 째 방법 에서'키'를 쉽게 얻 을 수 있 는 것 이 아니다.
우 리 는 당시 에 정 보 를 복사 해서 키 값 을 직접 사용 할 수 있다 고 언급 했 지만,이러한 방법 은 모든 연령 대 에 하나의 데 이 터 를 저장 하기 때문에 많은 공간 을 낭비 했다.
그러나 우리 가 색인 만 저장 하고 이 색인 을 통 해 데 이 터 를 조회 한다 면?
사람 이 갓 태 어 난 것 이 0 살 이 고 최대 100 살 까지 살 수 있다 고 가정 하면 우 리 는 길이 가 101 인 배열 을 만들어 야 한다.배열 의 아래 표 시 는 사람의 나이 에 해당 한다.그러면 0-17 의 모든 연령 에 우 리 는'18'을 저장 하고 18-65 에'18-65'를 저장 하 며 65 이상 에'>65'를 저장 해 야 한다.이렇게 하면 우 리 는 나 이 를 통 해 해당 하 는 색인 을 얻 고 색인 을 통 해 해당 하 는 데 이 터 를 조회 할 수 있다.
이러한 방법 은 위의 직접 방문 표 보다 더 복잡 해 보이 지만 키 값 을 바 꾸 기 어렵 고 데이터 가 공간 을 많이 차지 하 는 장면 에서 색인 을 통 해 접근 해 볼 수 있 습 니 다.
//Typescript
const ages:string[]=['<18','<18','<18',...'18-65','18-65','18-65',...'>65','>65','>65',...'>65'];
const ageKey:string=ages[age];
이렇게 하면 시 계 를 만 들 때 약간 번 거 롭 지만 데 이 터 를 처리 할 때 매우 간편 합 니 다!표 구동 의 전형 적 인 응용
표 구동 의 가장 큰 의 미 는 조건 판단(데이터)과 논 리 를 분리 하고 조건 을 설정 가능 한 표(대상 or 배열)로 관리 하 는 것 이다.
0-360°를 8 개의 서로 다른 공간 으로 나 누 지만 항상 if-else 로 실현 하지 마 세 요.
//JavaScript
const keys=['A','B','C','D','E','F','G','H'],
range=[45,90,135,180,225,270,315,360];
const degreeTkey=(rage)=>{
for(let i in range){
if(rage<=range[i]){
return keys[i];
}
}
}
const map={
'A':()=>{
//...
},
'B':()=>{
//...
},
//...
}
// :
map[degreeTkey(46)]();
if-else 대응 관계 복잡 한 문제 매 거 해결어떤 캐릭터 가 무슨 일 을 하 는 지,이것 은 매우 뚜렷 한 대응 관계 이기 때문에 배 운'매 거'는 왜 사용 하지 않 습 니까?
사실은 위 에서 언급 한[표 검색]과 비슷 합 니 다.우 리 는'시스템 관리자 의 조작 권한'문 제 를 들 었 습 니 다.
먼저 공용 인터페이스 Role Operation 을 정의 하고 서로 다른 캐릭터 가 할 수 있 는 동작 을 표시 합 니 다.
public interface RoleOperation {
String op();// op
}
그 다음 에 우 리 는 서로 다른 캐릭터 의 상황 을 모두 매 거 진 유형 에 맡 기 고 서로 다른 캐릭터 가 서로 다른 권한 을 가 진 매 거 진 유형RoleEnum
을 정의 한다.
public enum RoleEnum implements Role0peration {
// ( A )
ROLE_ ROOT_ _ADMIN {
@Override
public String op() {
return "ROLE_ ROOT_ ADMIN:" + " has AAA permission";
}
},
// ( B )
ROLE_ ORDER_ ADMIN {
@override
public String op() {
return "ROLE_ ORDER_ _ADMIN:" + " has BBB permission";
}
},
// ( C )
ROLE_ NORMAL {
@Override
public String op() {
return "ROLE_ NORMAL:" + "has CCC permission";
}
};
}
그리고 이렇게 되면 앞으로 만약 에 제 가 조건 을 확대 하고 싶다 면 매 거 진 유형 에 코드 를 추가 하면 됩 니 다.예전 의 코드 를 고 치 는 것 이 아니 라 안정 적 이지 않 습 니까?
public class JudgeRole {
public String judge( String roleName ) {
// ! if/else !
return RoleEnum.va1ue0f(roleName).op();
}
}
공장 모드 해결 if-else"분기 과 다"문제서로 다른 지점 에서 서로 다른 일 을 하 는 것 은 공장 모델 을 사용 하 는 계 기 를 제공 하 는 것 이 분명 하 다.우 리 는 서로 다른 상황 을 단독으로 정의 한 다음 에 공장 류 에 가서 집합 하면 된다.
우선,서로 다른 역할 에 대해 업무 유형 을 따로 정의 할 수 있 습 니 다.
// ( A )
public class RootAdminRole implements Role0peration {
private String roleName ;
public RootAdminRole( String roleName){
this.roleName = roleName ;
}
@Override
public String op() {
return roleName + "has AAA permission" ;
}
}
// ( B )
public class OrderAdminRole implements RoleOperation {
private String roleName ;
public OrderAdminRole( String roleName ) {
this.roleName = roleName ;
}
@Override
public String op() {
return roleName + "has BBB permission";
}
}
// ( C )
public class NormalRole implements RoleOperation {
private String roleName ;
public NormalRole( String roleName){
this.roleName = roleName;
}
@Override
public String op() {
return roleName + "has CCC permission";
}
}
다음은 공장 류RoleFactory
를 하나 더 써 서 위의 서로 다른 역할 을 취 합 한다.
public class RoleFactory {
static Map<String, Role0peration> roleOperationMap = new HashMap<>();
//
static {
role0perationMap.put( "ROLE_ ROOT_ ADMIN", new RootAdminRole("ROLE_ _ROOT_ ADMIN") ) :
roleOperationMap.put( "ROLE_ ORDER_ ADMIN", new OrderAdminRole("ROLE_ ORDER_ ADMIN") );
role0perationMap.put( "ROLE_ NORMAL", new NormalRole("ROLE_ NORMAL") );
}
pub1ic static RoleOperation getOp( String roleName ) {
return roleOperationMap.get( roleName ) ;
}
}
그 다음 에 위의 이 공장 을 통 해 업무 코드 호출 도 한 줄 의 코드 만 필요 합 니 다.if/else 역시 제거 되 었 습 니 다.
public class JudgeRole {
public String judge(String roleName){
// ! if/else !
return RoleFactory.get0p(roleName).op();
}
}
이렇게 되면 앞으로 조건 을 확장 하 는 것 도 쉬 워 집 니 다.새로운 코드 만 추가 하고 예전 의 업무 코드 를 움 직 이지 않 아 도 됩 니 다.'개폐 원칙'에 매우 부합 합 니 다.이제 2020 인 데 왜 단순히 if-else 를 사용 하 는 지 에 대한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 if-else 사용 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부 탁 드 리 겠 습 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
어떻게 자바 프로젝트 에서 if-else 를 대량으로 사용 하 는 것 을 피 합 니까?요약 하면 전략 매 거 는 매 거 에서 전략 모델 을 사용 하 는 것 이다.이른바 전략 모델 은 열 쇠 를 주 는 것 이다.특정한 약속 방식 에 따라 바로 열 수 있 는 문 을 찾 을 수 있다.예 를 들 어 내 가 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.