형태소 분석기는 웹 검색 엔진 만들기에서 만든 것과 차이가 없습니다. 여기에서도 즐겨찾기에 등록한 RSS 피드의 항목을 탐색하면 페이지 내용을 형태소 분석기로 분석합니다.
형태소 분석기는 정적 클래스로 제공합시다.
public static class MorphemeParser { }
형태소 분석기에는 필터링할 문자열과 접미사를 선언합니다.
static string[] filters = {" ",",",".","?","!","\r","\n","\t","!","?", "[","]","<",">","{","}","\"","'", "a","b","c","d","e","f","g","h","i", "j","k","l","m","n","o","p","q","r","s", "t","u","v","w","x","y","z"}; static string[] pf_filters = {"는","은","을","를","가","에","게", "에게","입니다","합니다"};
컨텐츠를 입력 인자로 받아 형태소 목록을 반환하는 메서드를 제공합시다.
public static List<Morpheme> Parse(string source)
형태소 목록을 보관할 컬렉션을 생성합니다.
List<Morpheme> mlist = new List<Morpheme>();
입력받은 소스에서 필터링할 문자열을 기준으로 문자열을 분할합니다.
string[] elems = source.Split(filters,StringSplitOptions.RemoveEmptyEntries);
분할한 각 문자열을 분석하여 분석 결과를 형태소 항목 컬렉션을 반환합니다.
foreach (string elem in elems) { ParseElem(elem, mlist); } return mlist;
분할한 각 문자열을 분석하는 메서드를 작성합시다.
private static void ParseElem(string elem, List<Morpheme> mlist)
필터링할 접미사로 등록한 각 접미사가 문자열에 포함하는지 파악하여 접미사를 필터링하는 작업을 수행합니다. 만약 접미사를 포함하고 있는 문자열이면 접미사를 뺀 부분 문자열로 형태소를 만들고 접미사를 포함하고 있지 않다면 문자열 자체로 형태소를 만듭니다. 여기에서는 접미사를 포함하는지 점검하는 부분과 접미사를 뺀 부분 문자열로 형태소를 만들거나 문자열 자체로 형태소를 만드는 부분은 별도의 메서드로 만들어 사용할게요.
foreach (string pf_filter in pf_filters) { if (CheckPostfix(pf_filter, elem)) { MakeElem(pf_filter, elem, mlist); return; } } RecordElem(elem, mlist);
필터링할 접미사가 포함하고 있는지 확인하는 메서드를 작성합시다.
private static bool CheckPostfix(string pf_filter, string elem)
먼저 접미사를 포함하는지 확인합니다. 그리고 포함하고 있다면 원본 문자열 길이에서 접미사 문자열의 길이를 빼어 뒷 부분의 문자열을 얻어옵니다. 그리고 얻어온 문자열과 접미사 문자열이 같으면 참을 반환합니다. 그렇지 않으면 거짓을 반환합니다.
if (elem.Contains(pf_filter)) { int pos = elem.Length - pf_filter.Length; string sub = elem.Substring(pos); if (sub == pf_filter) { return true; } } return false;
접미사를 뺀 문자열로 형태소를 만드는 메서드를 구현합시다.
private static void MakeElem(string pf_filter, string elem, List<Morpheme> mlist)
먼저 접미사를 뺀 문자열을 만듭니다. 그리고 형태소를 만들어 컬렉션에 추가하는 메서드를 호출합니다.
int pos = elem.Length - pf_filter.Length; string sub = elem.Substring(0, pos); RecordElem(sub, mlist);
형태소를 만들어 컬렉션에 추가하는 메서드를 구현합시다.
private static void RecordElem(string elem, List<Morpheme> mlist)
먼저 형태소 목록의 각 형태소의 이름과 추가할 이름이 같은 것이 있으면 형태소의 개수속성을 1 증가합니다. 같은 것이 없다면 형태소 개체를 생성하여 형태소 컬렉션에 추가합니다.
foreach (Morpheme mo in mlist) { if (mo.Name == elem) { mo.Count++; return; } } Morpheme mor = new Morpheme(elem, 1); mlist.Add(mor);
▷ MorphemeParser.cs
using System; using System.Collections.Generic; namespace RSSBrowserLib { /// <summary> /// 형태소 분석기 - 정적 클래스 /// </summary> public static class MorphemeParser { static string[] filters = {" ",",",".","?","!","\r","\n","\t","!","?", "[","]","<",">","{", "}","\"","'", "a","b","c","d","e","f","g","h", "i", "j","k","l","m", "n","o","p","q","r","s", "t","u","v","w","x","y","z"}; static string[] pf_filters={"는","은","을","를","가","에","게","에게","입니다","합니다"}; /// <summary> /// 형태소 분석 정적 메서드 /// </summary> /// <param name="source">원본</param> /// <returns>형태소 컬렉션</returns> public static List<Morpheme> Parse(string source) { List<Morpheme> mlist = new List<Morpheme>(); string[] elems = source.Split(filters, StringSplitOptions.RemoveEmptyEntries); foreach (string elem in elems) { ParseElem(elem, mlist); } return mlist; } private static void ParseElem(string elem, List<Morpheme> mlist) { foreach (string pf_filter in pf_filters) { if (CheckPostfix(pf_filter, elem)) { MakeElem(pf_filter, elem, mlist); return; } } RecordElem(elem, mlist); } private static void RecordElem(string elem, List<Morpheme> mlist) { foreach (Morpheme mo in mlist) { if (mo.Name == elem) { mo.Count++; return; } } Morpheme mor = new Morpheme(elem, 1); mlist.Add(mor); } private static void MakeElem(string pf_filter, string elem,List<Morpheme> mlist) { int pos = elem.Length - pf_filter.Length; string sub = elem.Substring(0, pos); RecordElem(sub, mlist); } private static bool CheckPostfix(string pf_filter, string elem) { if (elem.Contains(pf_filter)) { int pos = elem.Length - pf_filter.Length; string sub = elem.Substring(pos); if (sub == pf_filter) { return true; } } return false; } } }