[Java] 두 문자열간의 유사도 구하기

두개의 문자열이 있을때, 얼마나 유사한지를 백분율의 개념인 0~1사이의 값으로 확인할 수 있을까? 즉 똑같은 문자열이라면 1을 전혀 다른 문자열이라면 0이라는 값으로 말이다. 구글링해보니 edit distance 계산을 통해 얻을 수 있단다. 가장 일반적은 구현체는 Levenshtein의 Distance Algorithm이라고 하고, 그 구현 함수는 다음과 같다. (출처: http://rosettacode.org/wiki/Levenshtein_distance#Java)

private double similarity(String s1, String s2) {
    String longer = s1, shorter = s2;
	
    if (s1.length() < s2.length()) {
        longer = s2; 
        shorter = s1;
    }
	
    int longerLength = longer.length();
    if (longerLength == 0) return 1.0;

    return (longerLength - editDistance(longer, shorter)) / (double) longerLength;
}

private int editDistance(String s1, String s2) {
	s1 = s1.toLowerCase();
    s2 = s2.toLowerCase();
    int[] costs = new int[s2.length() + 1];
    
    for (int i = 0; i <= s1.length(); i++) {
        int lastValue = i;
        for (int j = 0; j <= s2.length(); j++) {
            if (i == 0) {
            	costs[j] = j;
            } else {
                if (j > 0) {
                    int newValue = costs[j - 1];
                    
                    if (s1.charAt(i - 1) != s2.charAt(j - 1)) {
                    	newValue = Math.min(Math.min(newValue, lastValue), costs[j]) + 1;
                    }
                    
                    costs[j - 1] = lastValue;
                    lastValue = newValue;
                }
            }
        }
        
        if (i > 0) costs[s2.length()] = lastValue;
    }
    
    return costs[s2.length()];
}

사용은 similarity 함수에 비교할 문자열 2개를 지정하면 비슷한 정도가 0~1 사이의 값으로 반환된다.

CAD 색상 테이블 (Color Table)

지리정보시스템(GIS)의 원시 데이터 중 CAD에 대한 시각화를 위한 색상 테이블을 정리한 표입니다.

0 (#000000)
1 (#FF0000)
2 (#FFFF00)
3 (#00FF00)
4 (#00FFFF)
5 (#0000FF)
6 (#FF00FF)
7 (#FFFFFF)
8 (#414141)
9 (#808080)
10 (#FF0000)
11 (#FFAAAA)
12 (#BD0000)
13 (#BD7E7E)
14 (#810000)
15 (#815656)
16 (#680000)
17 (#684545)
18 (#4F0000)
19 (#4F3535)
20 (#FF3F00)
21 (#FFBFAA)
22 (#BD2E00)
23 (#BD8D7E)
24 (#811F00)
25 (#816056)
26 (#681900)
27 (#684E45)
28 (#4F1300)
29 (#4F3B35)
30 (#FF7F00)
31 (#FFD4AA)
32 (#BD5E00)
33 (#BD9D7E)
34 (#814000)
35 (#816B56)
36 (#683400)
37 (#685645)
38 (#4F2700)
39 (#4F4235)
40 (#FFBF00)
41 (#FFEAAA)
42 (#BD8D00)
43 (#BDAD7E)
44 (#816000)
45 (#817656)
46 (#684E00)
47 (#685F45)
48 (#4F3B00)
49 (#4F4935)
50 (#FFFF00)
51 (#FFFFAA)
52 (#BDBD00)
53 (#BDBD7E)
54 (#818100)
55 (#818156)
56 (#686800)
57 (#686845)
58 (#4F4F00)
59 (#4F4F35)
60 (#BFFF00)
61 (#EAFFAA)
62 (#8DBD00)
63 (#ADBD7E)
64 (#608100)
65 (#768156)
66 (#4E6800)
67 (#5F6845)
68 (#3B4F00)
69 (#494F35)
70 (#7FFF00)
71 (#D4FFAA)
72 (#5EBD00)
73 (#9DBD7E)
74 (#408100)
75 (#6B8156)
76 (#346800)
77 (#566845)
78 (#274F00)
79 (#424F35)
80 (#3FFF00)
81 (#BFFFAA)
82 (#2EBD00)
83 (#8DBD7E)
84 (#1F8100)
85 (#608156)
86 (#196800)
87 (#4E6845)
88 (#134F00)
89 (#3B4F35)
90 (#00FF00)
91 (#AAFFAA)
92 (#00BD00)
93 (#7EBD7E)
94 (#008100)
95 (#568156)
96 (#006800)
97 (#456845)
98 (#004F00)
99 (#354F35)
100 (#00FF3F)
101 (#AAFFBF)
102 (#00BD2E)
103 (#7EBD8D)
104 (#00811F)
105 (#568160)
106 (#006819)
107 (#45684E)
108 (#004F13)
109 (#354F3B)
110 (#00FF7F)
111 (#AAFFD4)
112 (#00BD5E)
113 (#7EBD9D)
114 (#008140)
115 (#56816B)
116 (#006834)
117 (#456856)
118 (#004F27)
119 (#354F42)
120 (#00FFBF)
121 (#AAFFEA)
122 (#00BD8D)
123 (#7EBDAD)
124 (#008160)
125 (#568176)
126 (#00684E)
127 (#45685F)
128 (#004F3B)
129 (#354F49)
130 (#00FFFF)
131 (#AAFFFF)
132 (#00BDBD)
133 (#7EBDBD)
134 (#008181)
135 (#568181)
136 (#006868)
137 (#456868)
138 (#004F4F)
139 (#354F4F)
140 (#00BFFF)
141 (#AAEAFF)
142 (#008DBD)
143 (#7EADBD)
144 (#006081)
145 (#567681)
146 (#004E68)
147 (#455F68)
148 (#003B4F)
149 (#35494F)
150 (#007FFF)
151 (#AAD4FF)
152 (#005EBD)
153 (#7E9DBD)
154 (#004081)
155 (#566B81)
156 (#003468)
157 (#455668)
158 (#00274F)
159 (#35424F)
160 (#003FFF)
161 (#AABFFF)
162 (#002EBD)
163 (#7E8DBD)
164 (#001F81)
165 (#566081)
166 (#001968)
167 (#454E68)
168 (#00134F)
169 (#353B4F)
170 (#0000FF)
171 (#AAAAFF)
172 (#0000BD)
173 (#7E7EBD)
174 (#000081)
175 (#565681)
176 (#000068)
177 (#454568)
178 (#00004F)
179 (#35354F)
180 (#3F00FF)
181 (#BFAAFF)
182 (#2E00BD)
183 (#8D7EBD)
184 (#1F0081)
185 (#605681)
186 (#190068)
187 (#4E4568)
188 (#13004F)
189 (#3B354F)
190 (#7F00FF)
191 (#D4AAFF)
192 (#5E00BD)
193 (#9D7EBD)
194 (#400081)
195 (#6B5681)
196 (#340068)
197 (#564568)
198 (#27004F)
199 (#42354F)
200 (#BF00FF)
201 (#EAAAFF)
202 (#8D00BD)
203 (#AD7EBD)
204 (#600081)
205 (#765681)
206 (#4E0068)
207 (#5F4568)
208 (#3B004F)
209 (#49354F)
210 (#FF00FF)
211 (#FFAAFF)
212 (#BD00BD)
213 (#BD7EBD)
214 (#810081)
215 (#815681)
216 (#680068)
217 (#684568)
218 (#4F004F)
219 (#4F354F)
220 (#FF00BF)
221 (#FFAAEA)
222 (#BD008D)
223 (#BD7EAD)
224 (#810060)
225 (#815676)
226 (#68004E)
227 (#68455F)
228 (#4F003B)
229 (#4F3549)
230 (#FF007F)
231 (#FFAAD4)
232 (#BD005E)
233 (#BD7E9D)
234 (#810040)
235 (#81566B)
236 (#680034)
237 (#684556)
238 (#4F0027)
239 (#4F3542)
240 (#FF003F)
241 (#FFAABF)
242 (#BD002E)
243 (#BD7E8D)
244 (#81001F)
245 (#815660)
246 (#680019)
247 (#68454E)
248 (#4F0013)
249 (#4F353B)
250 (#333333)
251 (#505050)
252 (#696969)
253 (#828282)
254 (#BEBEBE)
255 (#FFFFFF)

Java로 텍스트 파일 읽기

버퍼 방식으로 사용하여 빠르게 텍스트 파일을 읽는 예제 코드입니다. 제가 Java 아재라서, 새로운 Java의 더욱 효과적인 파일 읽기 API가 분명 있을것 같은데.. 혹 있다면 추천 부탁드리겠습니다.

package tst;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;

public class MainEntry {
	public static void main(String[] args) {
		String filePath = "D:\\__Data__\\DXF\\1_5000\\NGII_DTM_5000_울산_남구_35905\\35905090.dxf";

		FileInputStream fs = null;
		InputStreamReader isr = null;
		BufferedReader br = null;
		
		try {
			long startTime = System.currentTimeMillis();
			
			fs = new FileInputStream(filePath);
			isr = new InputStreamReader(fs, "euc-kr");
			br = new BufferedReader(isr);
			
			String line = null;
			while((line = br.readLine()) != null) {
				//System.out.println(line);
			}
			
			long finishTime = System.currentTimeMillis();
			System.out.println("소요시간: " + (finishTime - startTime) + " ms");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if(br != null) br.close();
				if(isr != null) isr.close();
				if(fs != null) fs.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

위의 코드로 7.52MB 크기의 파일을 모두 읽는데, 약 0.13초정도 소요됩니다. 사용하고 있는 개발 환경은 i7-6700HQ@2.60GHz의 RAM 16GB 노트북입니다.

Python에서 외부 데이터 파일 읽기

파이썬에서 다양한 데이터 파일을 읽어오는 코드를 정리한 글로 추후 빠르게 참조하기 위한 목적으로 작성 되었습니다.

CSV 파일 읽기

import csv

rows = []
with open('../data/fileName.csv') as csvfile:
    csvreader = csv.reader(csvfile)
    next(csvreader, None)
    for row in csvreader:
        rows.append(row)

3번의 next 함수는 csv 파일의 첫줄에 있는 필드명을 건너뛰기 위함입니다. rows에 데이터가 저장됩니다.

JSON 파일 읽기

import json

with open('../data/fileName.json') as jsonfile:
    data = json.load(jsonfile)
    value_plainType = data["key1"]
    value_arrayType = data["key2"]
    value_dictionaryType = data["key3"]

    print(value_plainType)
    print(value_arrayType)
    print(value_dictionaryType["name"])

위의 fileName.json 파일의 내용이 다음과 같을때..

{
    "key1" : "string/numeric/bool",
    "key2" : [1, 2, 3, 4, 5],
    "key3" : { "name":"DoWise", "age": 12 }
}

출력 결과는 다음과 같습니다.

string/numeric/bool
[1, 2, 3, 4, 5]
DoWise

vi 편집기 명령 정리

이 글은 콘솔 환경에서 텍스트를 편집할 수 있는 vi 편집기 사용을 위해 요약한 글로 vi를 처음 접하는 분들은 다른 글을 참조하시기 바랍니다.

vi는 총 4가지 상태를 가지며 다음과 같은 상태 전환이 이루어집니다.

EX 모드

  • 변경된 내용 저장 w
  • 변경된 내용 저장하고 종료 wq
  • 변경된 내용 무시하고 종료 q!
  • 종료 q
  • 문자열 검색(예: boy) /boy
    • 다음 검색 문자열 n
    • 이전 검색 문자열 N
  • 문자열 변경(예: boy를 guy로 변경) %s/boy/guy/ig
  • 줄 번호 표시 set nu
  • 줄 번호 감추기 set nonu

명령 모드

  • 현재 커서 위치에서 편집 모드로 전환 i
  • 현재 커서 위치 줄의 첫문자 위치에서 편집 모드로 전환 I
  • 현재 커서의 바로 뒤에서 편집 모드로 전환 a
  • 현재 커서 위치 줄의 마지막 위치에서 편집 모드로 전환 A
  • 왼쪽으로 커서 위치 이동 h, ←
  • 오른쪽으로 커서 위치 이동 l, →
  • 위쪽으로 커서 위치 이동 k, ↑
  • 아래쪽으로 커서 위치 이동 j, ↓
  • 다음 단어 단위로 커서 이동 w
  • 이전 단어 단위로 커서 이동 b
  • 커서 위치 라인의 첫 문자로 이동 ^, 0
  • 커서 위치 라인의 끝 문자로 이동 $
  • 마지막 라인으로 이동 G
  • 100번째(1부터 시작) 라인으로 이동 100G
  • 편집된 내용 되돌리기 u
  • 커서 위치 한글자 삭제 x
  • 커서 위치를 포함해 세 글자 삭제 3x
  • 커서 앞의 글자 삭제 X
  • 커서 위치의 단어 단위로 삭제 dw
  • 커서 위치 줄 삭제 dd
  • 커서 위치의 줄을 포함해 세 줄 삭제 3dd
  • 커서 앞의 글자 삭제 X
  • 커서 위치에서 줄 끝 문자까지 삭제 D
  • 커서 위치의 줄을 버퍼에 복사 yy
  • 커서 위치의 줄을 포함해 세 줄을 버퍼에 복사 3yy
  • 버퍼에 복사된 문자열을 커서 위치에 붙여넣기 p
  • 버퍼에 복사된 문자열을 커서의 앞 위치에 붙여넣기 P
  • 한 글자만 수정 r
  • 커서 다음 위치에 빈줄 추가 o
  • 커서 이전 위치에 빈줄 추가 O
  • 커서 위치의 라인과 다음 라인을 한 라인으로 붙임 J

비주얼 모드

  • 글자 단위로 선택(명령모드에서 전환시) v
  • 라인 단위로 선택(명령모드에서 전환시) V
  • 블럭 단위로 선택(명령모드에서 전환시) ^v
  • 선택된 텍스트를 버퍼에 복사 y
  • 선택된 텍스트를 삭제 d, x