배열
배열이란 영어로 Array라고 한다. 배열은 연관된 데이터를 모아서 관리하기 위해서 사용하는 데이터 타입이다. 변수가 하나의 데이터를 임시로 저장하기 위한 것이라면 배열은 여러 개의 데이터를 저장하기 위한 것이라고 할 수 있다. 아래의 예제를 보자. 변수 name에는 문자 egoing이 할당되었다. 이제부터 name을 호출하면 문자 egoing을 사용할 수 있다.
name = 'egoing' puts name
배열의 생성
그렇다면 여러 개의 데이터를 하나의 변수에 담아서 관리할 수 있는 방법은 없을까? 있다. 배열을 쓰면 된다. 변수 member에 회원정보를 담아보자. 대괄호([])는 배열을 만드는 기호다. 대괄호 안에 데이터를 콤마(,)로 구분해서 나열하면 배열이 된다.
member = ['egoing', 'k8805', 'sorialgi']
하나의 변수에 3개의 데이터를 담았다. 각각의 데이터를 원소(element)라고 부른다. 자 그럼 이 데이터를 꺼내오려면 어떻게 해야 할까? 아래의 예제를 보자.
member = ['egoing', 'k8805', 'sorialgi'] puts member[0] puts member[1] puts member[2]
결과는 다음과 같다.
egoing k8805 sorialgi
즉 배열에 담겨있는 값을 가져올 때는 대괄호 안에 숫자를 넣는다. 이 숫자를 색인(index)라고 부르고 0부터 시작한다. 이 값을 이용해서 배열에 저장된 원소를 찾을 수 있다.
배열이 없다면
그렇다면 배열이 없다면 어떻게 될까? 예를 들어 맴버의 이름을 제공하는 메소드를 만들어야 한다고 해보자. 그런데 메소드는 하나의 값만을 반환(return) 할 수 있다. 아래의 예를 보자.
def get_member1 return 'egoing' end puts get_member1() def get_member2 return 'k8805' end puts get_member2() def get_member3 return 'sorialgi' end puts get_member3()
하나의 메소드는 하나의 값만을 반환할 수 있기 때문에 위와 같이 각각의 회원 정보를 반환하는 메소드수를 만들었다.
이번엔 배열을 이용한 아래의 코드를 보자. 맴버를 담고 있는 배열을 반환하고 있다. 간단하지 않은가?
def get_member() return ['egoing', 'k8805', 'sorialgi'] end puts get_member()
배열의 사용
배열의 진가는 반복문과 결합했을 때 나타난다. 반복문으로 배열에 담긴 정보를 하나씩 꺼내서 처리 할 수 있기 때문이다. 다음 예제를 보자.
def get_members return ['egoing', 'k8805', 'sorialgi'] end members = get_members() for index in 0 ... members.size puts members[index].capitalize end
결과는 아래와 같다.
Egoing K8805 Sorialgi
위의 예제에서 주목해야 할 것은 반복문과 배열을 결합한 부분이다. 반복문을 이용해서 배열 members의 내용을 하나씩 꺼낸 후에 이름의 첫글자를 대문자로 변경한 후에 출력하고 있다. (알파벳의 첫글자를 대문자로 만드는 방법은 String.captalize를 참고) 정리하면, 배열이란 연관된 정보를 하나의 그룹으로 관리하기 위해서 사용한다. 그리고 그 정보를 처리 할 때는 반복문을 이용한다.
반복자 - iterator
each
앞선 반복문 수업에서 while과 for 문을 알아봤다. 하지만 ruby에서는 이런 것들보다는 반복자라는 것을 더 많이 쓴다. 다음 코드를 보자. 결과는 배열의 값을 하나씩 출력한다.
arr = [1, 2, 3, 4, 5] arr.each { |a| puts a }
arr = [1, 2, 3, 4, 5]
arr은 1부터 5까지의 숫자가 담겨있는 배열이다.
arr.each
each는 배열에 내장되어 있는 반복자(iterator)다. 이 반복자 뒤에 따라오는 { |a| puts a } 가 배열의 원자 수 만큼 반복된다.
|a|
파이프(|) 사이의 a는 인자다. 반복이 실행될 때마다 인자 a에는 배열의 값이 담겨진다. a는 인자의 이름이기 때문에 다른 이름으로 변경할 수 있다. 하지만 그 인자를 사용하는 코드의 이름도 다음과 같이 변경돼야 한다. { |b| puts b }
puts a
인자 a (|a|)의 값이 변수 a에 할당 됐기때문에 puts a는 각각의 원소를 화면에 출력한다.
위의 코드는 아래와 같이 사용할 수도 있다. do와 end가 열리는 중괄호({)와 닫히는 중괄호(})의 역할을 하고 있다.
[1, 2, 3, 4, 5].each do |a| puts "This is #{a}" end
map
each는 반복작업이 목적이다. map은 each와 비슷하지만 배열의 내용을 바꾸는 것이 목적이다. 다음 예를 보자.
fruit = ['apple', 'orange', 'grape'] fruit = fruit.map { |e| e + ' is delicious' } puts fruit
결과는 아래와 같다.
apple is delicious orange is delicious grape is delicious
배열 제어
배열은 복수의 데이터를 효율적으로 관리, 전달하기 위한 목적으로 고안된 데이터 타입이다. 따라서 데이터의 추가/수정/삭제와 같은 일을 편리하게 할 수 있도록 돕는 다양한 기능을 가지고 있다. 몇가지 중요한 기능들만 살펴보자.
배열의 생성
위에서 대괄호를 이용해서 배열을 생성하는 법을 알아봤다. 아래 방법은 new 메소드를 이용한 방법이다.
아래 예제와 같은 문법적인 설명은 객체지향 수업에서 다루게 될 것이다.
arr = Array.new()
다음은 배열을 똑같은 글자로 채우는 방법이다. 아래와 같은 방법으로 coding everybody라는 값이 채워진 10개짜리 원소를 가진 배열을 만들었다.
arr = Array.new(10, 'coding everybody')
다음은 1부터 10까지의 숫자로 채워진 배열을 만드는 코드다.
arr = Array(1..10)
배열의 크기
아래와 같은 방법을 배열의 크기를 알아낼 수 있다
arr = [1, 2, 3, 4, 5] puts arr.length puts arr.size
배열의 조작
추가
다음은 배열의 끝에 원소를 추가하는 방법이다. 배열 arr는 a, b, c, d, e이 됐다. 배열에 값을 추가하는 것을 푸쉬라고 한다.
arr = ['a', 'b', 'c', 'd', 'e'] arr << 'f' puts arr
아래는 위와 같은 의미다.
arr = ['a', 'b', 'c', 'd', 'e'] arr.push('f') puts arr
다음은 배열의 시작점에 원소를 추가하는 방법이다. 배열 arr은 z, a, b, c, d, e가 됐다.
arr = ['a', 'b', 'c', 'd', 'e'] arr.unshift('z') puts arr
제거
다음은 배열 시작점에 있는 원소 두개를 배열 arr에서 제거한다. 결과는 c, d, e다.
arr = ['a', 'b', 'c', 'd', 'e'] arr.shift(2) puts arr
다음은 배열 끝점의 원소 두개를 배열 arr에서 제거한다. 결과는 a, b, c다.
arr = ['a', 'b', 'c', 'd', 'e'] arr.pop(2) puts arr
정렬
정렬을 하고 싶다면 아래와 같이 한다. 결과는 a, b, c, d, e 다.
li = ['c', 'e', 'a', 'b', 'd'] li.sort! puts li
역순으로 정렬하고 싶다면 아래와 같이 한다. 결과는 e, d, c, b, a 다.
li = ['c', 'e', 'a', 'b', 'd'] li.sort! { |x, y| y <=> x } puts li
hash(연관배열)
지금까지 살펴본 배열은 원소에 대한 식별자(인덱스)로 숫자를 사용했다. 데이터가 추가되면 배열 전체에서 중복되지 않는 인덱스가 자동으로 만들어져서 그 데이터에 대한 식별자가 된다. 만약 인덱스로 문자를 사용하고 싶다면 해쉬(hash)를 사용해야 한다. 다른 언어에서는 연관배열(associative array) 또는 사전(dictionary)라고 한다.
해쉬 생성
다음은 해쉬를 만드는 법이다.
grades = { 'egoing' => 10, 'k8805' => 6 , 'sorialgi' => 80}
위의 예제에서 egoing은 key가 되고, 10은 value가 된다. 아래는 해쉬를 만드는 다른 방법이다.
grades = Hash.new grades['egoing'] = 10 grades['k8805'] = 6 grades['sorialgi'] = 80
다음은 특정한 key의 값을 가져오는 법이다. 결과는 80이다.
grades = { 'egoing' => 10, 'k8805' => 6 , 'sorialgi' => 80} puts grades['sorialgi']
다음은 해쉬의 데이터를 기준으로 반복작업을 하는 방법이다. 반복자(iterator) each를 사용하고 있다.
grades = { 'egoing' => 10, 'k8805' => 6 , 'sorialgi' => 80} grades.each{ |k,v| puts "Key : #{k} \t Value : #{v}" }
결과는 아래와 같다.
Key : egoing Value : 10 Key : k8805 Value : 6 Key : sorialgi Value : 80
해쉬의 반복자는 인자로 두개의 값을 받는다. |k, v|에는 각각의 key와 value값이 담기도록 약속되어 있다. puts 안에 \t 기호는 문자 탭(tab)을 의미한다. 일정한 간격으로 문자를 정렬하기 위해서 사용했다.
해쉬와 배열
해쉬는 인덱스가 있는 데이터를 그룹핑하기에 좋은 데이터 타입이다. 만약 색인이 중복된다면 같은 색인을 가지고 있는 이전 데이터는 새로운 데이터로 덮어쓰기 될 것이다. 따라서 해쉬에서 색인은 유일무일하게 value를 식별하는 식별자여야 한다. 식별자가 있는 데이터는 해쉬를 사용하는 것이 더 빠르고, 편리하다. 반대로 식별자가 없는 데이터는 배열을 사용한다.