Creative Commons License

Microsoft .NET

닷넷!시작하기
닷넷! Ver 2.0~
닷넷!스킬업
웹개발
윈폼개발
실용모듈개발
Tip & Tech
하루 한 문법

Microsoft .NET 개발자들을 위한 공간입니다. 기초강의에서 부터 고급 기술 정보 및 팁등을 다루도록 하겠습니다.

.

닷넷!스킬업

닷넷 기술을 조금 더 깊이 다루고자 합니다. 특정 주제를 정하지 않고 이슈 발생 시 마다 체계적으로 정리하여 공유하겠습니다. 이전 자료를 옮겨온 곳이기도 합니다.

배열 요소 검색

작성자 : 박종명
최초 작성일 : 2010-01-06 (수요일)
최종 수정일 : 2010-01-06 (수요일)
조회 수 : 3229

오랜만에 기술란에 끄적여 보네요...

언젠가 부터 경직된 사고와 귀차니즘으로 기술관련 글을 활발히 올리지 못하고 있네요
너무 간단한거 올리려니 좀 그렇고, 좀 복잡한거 올리려니 귀차니즘이 발동하고 ㅡ.ㅡ;

올해는 다시 맘을 다잡고 간단하던 복잡하던, 예전처럼(?) 사이트 관리를 잘 해나가야 겠다는 생각은 우선,듭니다^^

오늘 작성할 글은 '복수의 자료'에서 찾고자 하는 자료가 있는지 '검색'하는 것을 알아봅니다

이 주제를 작성하게 된 계기가 있습니다.
언젠가부터, 이 사이트에 지랄맞은 광고 댓글이 무데기로 올라오기 시작했습니다. 그것도 모두 영문으로다가...
간혹 보신분도 있겠지만, 사이트 메인 우측에 댓글을 뿌려 주는데 그 영역에 온통 영문이 나열된 경우입니다

수동으로 그때 그때 삭제하고는 있지만, 정말 귀찮더군요
그렇다고 해서 댓글 입력 시 필터룰을 주기에는 좀 그렇구.. 해서 , 일단 IP를 막기로 했습니다
광고댓글의 대부분이 유사 IP 에서 올라오더군요.. 자동 등록 프로그램을 사용하는 듯 합니다. 줸장...

사설이 길었네요.. 여튼 이 로직을 구현하다 복수자료 검색과 관련해 글을 좀 끄적여 보고 싶었습니다

--------------------------------------------------------------------------------------------------------------------------------------

복수개의 자료저장 구조하면 딱! 떠오르는게 '배열'이죠
다른 자료구조도 있겠지만, 가장 심플한 배열을 이용하기로 합니다

아래와 같은 요구사항이 있습니다

다음과 같이 문자열 배열이 있다
string[] sourceArray = { "홍길동","박길동", "김길동" };

배열에서 특정 이름이 존재하는지 검색해야 한다... 입니다. 간단하죠?

여러가지 구현 방법이 떠 오릅니다

참고로 아래 전개되는 내용은 닷넷 2.0 기반 코드 예제입니다
그리고 닷넷 3.0 부터 지원하는 LINQ 를 이용하면 배열 요소를 통합되고 일관된 쿼리 구문으로 검색할 수 있습니다
다만 이 글에서는 이 기법은 논외입니다


1. IndexOf 이용하기
아마 대부분의 사람들이 떠 올리지 않았나 싶습니다

Array.IndexOf 메서드는 검색값이 존재하는 첫 번째 요소에 대한 인덱스를 반환해 주죠
만일 존재하지 않는다면, -1을 반환합니다

저는 인덱스에는 관심이 없고 존재 유/무만 관심이 있기 때문에 boolean으로 반환하도록 구현합니다

static string[] sourceArray = { "홍길동","박길동", "김길동" };

static void Main(string[] args)
{
    bool isExists = ExistsCheckUsingIndexOf();            
    Console.WriteLine(isExists);
}

static bool ExistsCheckUsingIndexOf()
{
    int index = Array.IndexOf<string>(sourceArray, "김길동");            
    if (index < 0) return false;
    else return true;
}


2. BinarySearch 이용하기
두번째로 이진탐색을 이용해서 검색할 수도 있습니다
Array.BinarySearch 메서드역시 검색값이 존재하는 요소의 인덱스를 반환합니다
다만, BinarySearch를 이용할 경우 배열은 정렬되어 있어야 합니다

이진탐색과 정렬에 관련된 내용은 다음 글을 참고해 주세요
=> 이진탐색 구현하기

다음과 같이 구현합니다

static string[] sourceArray = { "홍길동","박길동", "김길동" };

static void Main(string[] args)
{
     bool isExists = ExistsCheckUsingBinarySearch();            
     Console.WriteLine(isExists);
}
       
static bool ExistsCheckUsingBinarySearch()
{            
    Array.Sort<string>(sourceArray);
    int index = Array.BinarySearch<string>(sourceArray, "김길동");            
    if (index < 0) return false;
    else return true;
}

이진탐색을 이용할 경우, 검색속도가 빠르다는 장점이 있습니다
이진 탐색의 경우 O(log n) 연산인 반면, IndexOf 는 O(n) 연산입니다
배열에 저장된 요소가 많으면 많을 수록 더 효과를 보겠지요

단, 이진 탐색은 배열이 정렬되어 있어야 한다는 조건이 있기 때문에 정렬비용이 들 수도 있습니다
배열의 요소 수 및 미리 정렬된 구조인지에 따라 최적의 결정을 하면 되겠습니다


3. Predicate 이용하기

닷넷 2.0에 추가된 조건자 기반 검색으로도 구현할 수 있습니다
Array.Exists 메서드는 지정한 조건자의 조건에 일치하는 요소가 포함되는지 여부를 반환합니다
Exists 메서드의 구문은 다음과 같습니다

public static bool Exists<T> (
                 T[] array,
                 Predicate<T> match
)

여기서 독특한게 Predicate 인데요, 이것은 델리케이트입니다
즉 Predicate 델리게이트가 참조하는 메서드가 조건식이 되며, 배열의 각 요소들은 이 조건식에 의해 평가됩니다
아래와 같이 구현합니다

static string[] sourceArray = { "홍길동","박길동", "김길동" };

static void Main(string[] args)
{
    bool isExists = ExistsCheckUsingPredicate();            
    Console.WriteLine(isExists);
}

static bool ExistsCheckUsingPredicate()
{
    return Array.Exists<string>(sourceArray, PredicateMethod);   
}

private static bool PredicateMethod(String s)
{
    if (s == "김길동")
        return true;
    else
        return false;
}

Predicate 방식을 이용할 경우 조건식을 입맞에 맞게 구현할 수 있다는 장점이 있습니다
예를 들어 배열 요소 중 맨 처음 글자가 '홍'으로 시작하는 요소를 검색할 수도 있습니다
다음처럼,
private static bool PredicateMethod(String s)
{
    if (s.Substring(0,1) == "홍") //조건을 입맞에 맞도록 구현할 수 있다
        return true;
    else
        return false;
}

이는 Exists 보다는 Array.FindAll 메서드를 이용하면 더 효과를 볼 수 있겠네요
예를 들어 배열의 요소 중, 마지막 글자가 '동'으로 끝나는 모든 요소를 반환하라... 라는 식이죠..

그리고 마지막으로 한가지만 더 집고 넘어가겠습니다.
위와 같이 구현했을 경우,

다음처럼 검색 대상 문자를 매개변수로 취하는 경우 애매해 집니다
static bool ExistsCheckUsingPredicate(string searchString)
{
    return Array.Exists<string>(sourceArray, PredicateMethod);              
}

어떻게 해야 할까요???

답은 바로 그 유명한(?) 익명메서드 기법을 이용하는 것입니다. 다음처럼...

static string[] sourceArray = { "홍길동","박길동", "김길동" };

static void Main(string[] args)
{
    bool isExists = ExistsCheckUsingPredicate("김길동");            
    Console.WriteLine(isExists);
}      

static bool ExistsCheckUsingPredicate(string searchString)
{           
    return Array.Exists(sourceArray,
        delegate(string s)
        {
            if (s == searchString)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        );      
}

이름
비밀번호
홈페이지
JD <- 왼쪽의 문자를 오른쪽 박스에 똑같이 입력해 주세요