ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TIL #6 - 배열 활용 (1)
    프로그래밍/TIL(국비과정) 2020. 4. 1. 20:04

    #배열을 여러 방면으로 다루어 보는 프로그램

    배열을 여러가지 방법으로 다루는 메소드들을 본다. 

    String 타입의 배열과 int 타입 배열들이 뒤섞여 있으니 주의 

    MyArray.java

     

    1. contains메소드 

    배열 안에 내가 찾는 값 keyword가 있는지 없는지 참/거짓으로 알려주는 메소드다. 

    public static boolean contains(String[] array, String keyword) {
    		for(int i = 0; i < array.length; i++) {
    			if(keyword.equals(array[i])) {
    				return true; // 같은 값이 있으면 true
    			}
    		}
    		return false; // 없으면 false
    	}

    매개변수로 String 배열과, String 키워드(내가 찾는값)을 두고 

    배열의 길이만큼 for문을 실행하며 

    keyword와 배열 요소들을 하나씩 비교한다. 

    만약 같은 값이 있으면 return true 이고 for문을 다 돌때까지 찾지 못하면 return false가 된다.

     

    2. indexOf 메소드 

    찾는 값 keyword의 위치를 알려주는 메소드이다. 

    public static int indexOf(int[] array, int keyword) {
    		for(int i = 0; i < array.length; i++) {
    			if(keyword == array[i]) {
    				return i; // 찾는 값이 있는 경우 해당 인덱스 알려주기 
    			}
    		}
    		return -1; 
    	}
    	

    위의 contains와는 다르게 true/ false 형태가 아닌 int 형태로 

    찾는 값 keyword의 index값을 리턴해준다. 

     

    3. lastIndexOf 메소드 

    위의 indexOf 메소드를 이를테면 거꾸로 수행하는 형태의 메소드이다. 

    public static int lastIndexOf(String[] array, String keyword) {
    		for(int i = array.length -1; i >= 0; i--) {
    			if(keyword.equals(array[i])) {
    				return i; 
    			}
    		}
    		return -1; 
    	}

    for문을 보면 앞서 수행했던 for문들과는 다르게 i의 시작을 배열의 길이 끝 부터 시작한다. 

    그리고 0보다 작거나 같을 때까지 i를 1씩 감소시키며 if문을 수행한다. 

    결과는 위의 indexOf 메소드와 같이 나온다. 

     

    4. size 메소드 

    배열의 길이를 구하는 메소드이다. 

    사실 메소드를 굳이 구현하지 않아도 되지만 그냥 했다. 

    public static int size(String[] array) {
    		return array.length;
    	}

    다들 아는 그 .length가 들어있을 뿐이다. 

     

    5. expand 메소드 

    배열 크기를 1 늘려주는 메소드이다. 

    private static int[] expand(int[] array) {
    	// array 값을 복사해서 저장할 temp 배열을 만듦
    	int[] temp = new int[array.length];
    		
    	for(int i = 0; i < array.length; i++) {
    		temp[i] = array[i]; 
    		// 배열 안의 데이터도 모두 temp 안에 넣어줌 
    		}
    		
    	array = new int[temp.length+1];
    	// temp 배열에서 1 추가한 배열을 array 배열에 넣음
    		
    	for(int i = 0; i < temp.length; i++) {
    		array[i] = temp[i];
    		// temp의 데이터를 array 데이터에 넣음 
    	}
    	return array; // 끝
    }

    배열의 크기를 늘려줄 때는 기존에 내가 크기를 변경시키고자 하는 배열을 복사해 놓을 temp 배열을 따로 만들어야한다. 

    물론 temp 배열은 내가 크기를 바꿀 배열 array의 길이와 같은 길이의 배열이다.

    temp를 만들었다면, temp 배열 안에 array 배열의 데이터를 모두 넣어준다. 

    복사 작업이다. 

    이렇게 해주어야 데이터 손상이 없다. 

    그런 후 temp 배열의 길이에 +1을 한다. 

    그 다음 temp 배열의 모든 것을 array에 넣는다. 

    그러면 +1 된 temp 배열의 것들이 array에 들어가 array는 +1된 형태를 가질 수 있게 된다. 

     

    6. add 메소드 

    위의 expand가 배열의 크기를 1늘려준 메소드라면 add 메소드는 1 늘어난 배열에 요소를 추가하는 메소드이다. 

    expand가 만들어졌다는 전제하에 작동한다. 

    public static int[] add(int[] array, int element) {
    	// array 배열의 크기를 index에 저장해 둔다
    	int index = array.length;
    	// array = {1. 2}
    	// array.length = 2
    
    	// 위에서 만든 expand메소드를 이용해 array 배열을 1 증가시킨다.
    	array = expand(array);
    	// array.length = 3
    	// 여기서 array의 마지막 index 번호는 2이다.
    	array[index] = element;
    	return array;
    	}

     add 메소드의 경우엔 적용시킬 배열과 추가할 요소 element 매개변수가 필요하다. 

    먼저 index 변수에 배열의 길이를 저장한다. 

    그런 후 array 배열에 expand 메소드를 적용시켜 길이를 1 늘린다. 

    그런 후 앞서 저장했던 길이를 늘리기 전의 array의 길이를 저장했던 index를 여기서 불러온다 

    index는 늘린 후의 array의 마지막 인덱스가 된다. 

    그곳에 넣고자 하는 요소값 element를 넣는다. 

    배열의 길이는 크기-1 이다. 

    그렇기 때문에 앞에서 크기를 +1하기 전의 배열의 길이가 +1 한 후의 배열에게 있어서 마지막 배열의 인덱스가 된다. 

     

    7. remove 메소드 (정리가 엉망이니 추후 보충하겠습니다..)

    위에서 늘리고 추가하는 메소드를 만들었으니 이번에는 삭제하는 메소드이다. 

    추가하는 메소드는 배열의 크기와 그 속에 요소를 각각 따로 만들었지만 

    remove 메소드는 배열의 크기도 줄이고 요소를 없애는 작업까지 동시에 진행한다. 

    public static int[] remove(int[] array, int element) {
    
    	// 앞에서 만든 indexOf()
    	int index = indexOf(array, element);
    
    
    	if (index != -1) { // 배열이 존재한다면 ( 배열 인덱스 번호가 -1이 아니면)
    
    		// 앞 배열
    		int[] front = new int[index];
    		// front 배열을 만들어 index 만큼 할당
    		for (int i = 0; i < front.length; i++) {
    			front[i] = array[i];
    			
    		}
    
    		// 뒷 배열
    		int[] back = new int[array.length - front.length - 1];
    
    		int backIndex = 0;
    		for (int i = index + 1; i < array.length; i++) {
    				back[backIndex] = array[i];
    				backIndex++;
    		}
    
    		array = new int[front.length + back.length];
    
    		for (int i = 0; i < front.length; i++) {
    			array[i] = front[i];
    		}
    
    		backIndex = front.length;
    		for (int i = 0; i < back.length; i++) {
    			array[backIndex] = back[i];
    			backIndex++;
    			}
    		}
    
    	return array;
    
    }

     remove 메소드의 매개변수는 마찬가지로 배열과 제거하고자 하는 요소이다. 

    삭제 작업은 조금 복잡하다. 

    만약 {1, 2, 3, 4, 5} 라는 배열이 있고 그 중에 3이라는 값을 없애려고 한다면 

    우리는 3을 기준으로 3보다 앞에 있는 배열, 3보다 뒤에 있는 배열 

    두 배열로 나눈 후, 3을 없애고 

    다시 두 배열을 합쳐주는 작업을 해야한다. 

    이해하는데에 너무 힘들었다. 

    차근차근 보자. 

     

    먼저 삭제하고자 하는 값을 찾아야한다. 

    이 단계는 간단하다. 

    앞서 만들었던 indexOf 메소드를 이용해 삭제하고자 하는 값을 찾아낸다. 

    int index = indexOf(array, element); 

    그리고 삭제하고자하는 값을 찾아 index 변수에 넣어둔다.

     

    그 다음엔 이젠 없애고자 하는 배열 기준으로 앞, 뒤 배열을 나누는 작업이다. 

    앞서 봤던 예시는 예쁘게 정중앙의 요소값을 없애면 됐다(3)

    그러나 우리가 없애고자 하는 배열이 맨 앞에 있다면 곤란하다. 

    배열 크기가 -1인 배열은 존재하지 않기 때문이다. 

    그렇기 때문에 if문을 이용해 index가 -1이 되지 않는 경우에 작업을 수행하도록 한다. 

     

    배열이 정상적인 것을 확인하고 

    먼저 앞 배열을 보자. 

    앞 배열의 경우엔 간단하다. 

    0부터 우리가 삭제하고자 하는 값 index 만큼의 크기를 가질 것이기 때문이다. 

    그렇기 때문에 앞배열의 선언은 아래와 같다 

    int[] front = new int[index];

    그리고 front 배열의 길이만큼 array 배열의 내용물을 그대로 넣어주면 된다. 

    0부터 시작하기 때문에 index 며 순서며 아무것도 신경쓸 것이 없어서 간단하다. 

     

    문제는 뒷배열이다. 

    뒷배열의 경우엔 index의 뒤부터 배열의 끝까지가 뒷배열의 크기가 된다. 

    그렇기 때문에 뒷배열의 선언은 아래와 같다. 

    int[] back = new int[array.length - front.length -1];

    이 부분이 굉장히 헷갈렸는데 찬찬히 보면 간단하다. 

    위의 예시를 다시 가져온다. 

    {1, 2, 3, 4, 5}

    여기서 우리가 3을 없애려고 했을 때 

    앞 배열은 없애려는 배열을 index에 담아서 

    int[] front = new int[index]; 

    즉 int[] front = new int[2]; 가 된다. 3이 인덱스 2에 있기 때문이다. 

    그 때 뒤쪽 배열은 3뒤부터 4, 5이다. 

    그럼 배열 전체 길이에서 앞 배열 길이를 빼면 없애려는 값 3 배열이 남아버린다. 

    앞 배열 길이가 2가 되기 때문에 없애려는 값 3이 제외되기 때문이다. 

    그렇기 때문에 -1을 해서 뒷배열 값에도 3의 자리를 빼주어야 한다. 

    그러면 오롯이 4와 5만 남는 깔끔한 뒷배열이 만들어진다. 

     

    그리고 또 하나, 뒷배열은 인덱스 번호가 앞배열과 다르게 0부터 시작하지 않는다. 

    혼돈이 생길 수 있기 때문에 뒷배열 인덱스를 0으로 초기화 시켜준다 . 

    int backIndex = 0;

    그런 다음 배열 요소를 뒷배열 요소에 넣어준다. 

    해당 작업을 수행하는 for문을 보면, 

    index +1 부터 시작한다. 그렇게 되면 제거하고자하는 값 뒤쪽부터 시작하게 된다. 

    거기부터 배열의 길이 끝까지 수행한다. 

    backIndex부터 시작해서 back을 위한 위치를 따로 만들어서 0에서 1부터 증가하면서 

    위치가 직접 지정되게 해야한다. 

    왜냐하면,,

    arr[i] 번째에 차례대로 front와 back을 넣어줘보자

    그럼 arr[i] = front[i], arr[i] = back[i]가 되는데 만약 front의 길이가 3이고 back의 길이가 2라고 가정해보자. 

    그럼 i는 종 5번 반복된다. 

    그럼 for문을 통해서 돌려보자. 

    array[i] = front[i] 일때를 먼저 본다. 

    i가 0일때 , i가 1일때, i가 2일때 모두 큰 문제가 없다. 

    그런데 i가 3일 때 문제가 생긴다. 왜냐하면 front는 길이가 3으로 인덱스가 0부터 2까지만 있기 때문이다.

    그럼 if문을 써서 front의 길이까지만 수행하도록 하자. 

    하지만 그렇다고 문제가 해결되진 않는다. 

    array[i] = back[i]에서 문제가 생기기 때문이다. 

    back역시 길이가 2로 인덱스가 0과 1밖에 없다. 

    즉 arr[3]은 어디에도 갈 곳이 없다. 

    이해가 안되면 그냥 어떻게든 이렇게 자리가 남아돈다던가 하는 문제가 생긴다는 것으로 생각하도록 한다. 

    (이 부분은 나도 아직 모호하기 때문에 좀 더 추가 설명 하도록 하겠다..)

    따라서 우리가 front와 back의 값을 다시 합쳐서 새로운 array에 복사할 때 

    for문 수행에 대해서 생각을 해볼 필요가 있다.

     

    우리는 그래서 backIndex를 통해서 back 배열을 컨트롤하는 방법을 택했다. 

    backIndex를 0으로 초기화 했다고 치고 

    back의 크기를 예시로 3이라고 하자. 

    그러면 for문의 i는 0 1 2가 된다. 

    그런데 array[0], array[1], arra[2]에는 무엇이 있을까? 

    이미 우리가 front 값을 입력한게 있기 때문에 값이 덮어진다. 

    그렇기 때문에 backIndex = 0이 아닌 걸로 초기화 해야한다. 

    front가 끝난 index가 되어야 할 것이다. 

    그럼 0 이 아닌 front.length로 초기화해야한다. 

    왜냐하면 배열의 마지막 index는 배열길이 -1 이기 때문이다. 

    따라서 front의 맨 마지막 idnex는 front.length-1이기 때문에 

    front가 끝난 다음 array가 back배열의 시작이 될 것이다. 

     

    만약, front의 크기가 5이고 back의 크기가 2일때 

    array의 새로운 크기는 얼마인가? 7이다. 

    그럼 array의 가능한 index는 0부터 6이 될 것이다. 

    arr[0] = front[0]

    arr[1] = front[1]

    arr[2] = front[2]

    arr[3] = front[3]

    arr[4] = back[0]

    arr[5] = back[1]

    arr[6] = back[2]

    위와 같이 된다. 

    즉, front가 끝나는 위치는 front.length-1이다. 

    그럼 array에서 front가 끝나고 처음으로 back을 집어넣을 위치는? front.length가 되는 것이다. 

     

    그렇기 때문에 back 배열을 복사하는 for문에서 backIndex = front.length; 가 된다. 

    거기서 부터 back배열이 시작하는 것이다. 

     

    8. removeByIndex 메소드 

    주어진 index에 따라 배열을 삭제하는 것이다. 

    remove와 다르게 인덱스를 보고 배열을 삭제한다. 

    	public static int[] removeByIndex(int[] arr, int index) {
    		if (index >= 0 && index < arr.length) {
    			// index가 0보다 크고, 배열 길이보다는 작으면
    			arr = remove(arr, arr[index]);
    			// 위의 remove 메소드로 삭제하고자하는 index와 배열을 함께 보낸다.
    		}
    		return arr;
    	}
    

    index값이 0보다 크고 배열 길이보다 작으면 

    위의 remove 메소드로 삭제하고자하는 index와 배열을 보낸다. 

     

     

    '프로그래밍 > TIL(국비과정)' 카테고리의 다른 글

    TIL #7 - 각종 출력, 입력, 조회 기능  (0) 2020.04.02
    TIL #6 - 배열 활용 (2)  (0) 2020.04.01
    TIL #5 - 배열  (0) 2020.03.31
    TIL #4 - 메소드, 배열 등  (0) 2020.03.30
    TIL #3 - Java 기초 등  (0) 2020.03.28

    댓글

Designed by Tistory.