source: trunk/gsdl/packages/kea/kea-3.0/weka/core/Range.java@ 8815

Last change on this file since 8815 was 8815, checked in by mdewsnip, 19 years ago

Kea 3.0, as downloaded from http://www.nzdl.org/kea but with CSTR_abstracts_test, CSTR_abstracts_train, Chinese_test, and Chinese_train directories removed.

  • Property svn:keywords set to Author Date Id Revision
File size: 11.2 KB
Line 
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17/*
18 * Range.java
19 * Copyright (C) 1999 Len Trigg
20 *
21 */
22
23package weka.core;
24
25import java.io.*;
26import java.util.*;
27
28/**
29 * Class representing a range of cardinal numbers. The range is set by a
30 * string representation such as: <P>
31 *
32 * <code>
33 * all
34 * first-last
35 * 1,2,3,4
36 * </code> <P>
37 * or combinations thereof. The range is internally converted from
38 * 1-based to 0-based (so methods that set or get numbers not in string
39 * format should use 0-based numbers).
40 *
41 * @author Len Trigg ([email protected])
42 * @version $Revision: 8815 $
43 */
44public class Range implements Serializable {
45
46 /** Record the string representations of the columns to delete */
47 Vector m_RangeStrings = new Vector();
48
49 /** Whether matching should be inverted */
50 boolean m_Invert;
51
52 /** The array of flags for whether an column is selected */
53 boolean [] m_SelectFlags;
54
55 /** Store the maximum value permitted in the range. -1 indicates that
56 no upper value has been set */
57 int m_Upper = -1;
58
59 /** Default constructor. */
60 public Range() {
61 }
62
63 /**
64 * Constructor to set initial range.
65 *
66 * @param rangeList the initial range
67 * @exception IllegalArgumentException if the range list is invalid
68 */
69 public Range(String rangeList) {
70
71 setRanges(rangeList);
72 }
73
74 /**
75 * Sets the value of "last".
76 *
77 * @param newUpper the value of "last"
78 */
79 public void setUpper(int newUpper) {
80
81 if (newUpper >= 0) {
82 m_Upper = newUpper;
83 setFlags();
84 }
85 }
86
87 /**
88 * Gets whether the range sense is inverted, i.e. all <i>except</i>
89 * the values included by the range string are selected.
90 *
91 * @return whether the matching sense is inverted
92 */
93 public boolean getInvert() {
94
95 return m_Invert;
96 }
97
98 /**
99 * Sets whether the range sense is inverted, i.e. all <i>except</i>
100 * the values included by the range string are selected.
101 *
102 * @param newSetting true if the matching sense is inverted
103 */
104 public void setInvert(boolean newSetting) {
105
106 m_Invert = newSetting;
107 }
108
109 /**
110 * Gets the string representing the selected range of values
111 *
112 * @return the range selection string
113 */
114 public String getRanges() {
115
116 String result = null;
117 Enumeration enum = m_RangeStrings.elements();
118 while (enum.hasMoreElements()) {
119 if (result == null) {
120 result = (String)enum.nextElement();
121 } else {
122 result += ',' + (String)enum.nextElement();
123 }
124 }
125 return (result == null) ? "" : result;
126 }
127
128 /**
129 * Sets the ranges from a string representation.
130 *
131 * @param rangeList the comma separated list of ranges. The empty
132 * string sets the range to empty.
133 * @exception IllegalArgumentException if the rangeList was not well formed
134 */
135 public void setRanges(String rangeList) {
136
137 Vector ranges = new Vector (10);
138
139 // Split the rangeList up into the vector
140 while (!rangeList.equals("")) {
141 String range = rangeList.trim();
142 int commaLoc = rangeList.indexOf(',');
143 if (commaLoc != -1) {
144 range = rangeList.substring(0, commaLoc).trim();
145 rangeList = rangeList.substring(commaLoc + 1).trim();
146 } else {
147 rangeList = "";
148 }
149 if (!range.equals("")) {
150 if (isValidRange(range)) {
151 ranges.addElement(range);
152 } else {
153 throw new IllegalArgumentException("Invalid range list at " + range
154 + rangeList);
155 }
156 }
157 }
158 m_RangeStrings = ranges;
159
160 if (m_Upper >= 0) {
161 setFlags();
162 }
163 }
164
165 /**
166 * Gets whether the supplied cardinal number is included in the current
167 * range.
168 *
169 * @param index the number of interest
170 * @return true if index is in the current range
171 * @exception RuntimeException if the upper limit of the range hasn't been defined
172 */
173 public boolean isInRange(int index) {
174
175 if (m_Upper == -1) {
176 throw new RuntimeException("No upper limit has been specified for range");
177 }
178 if (m_Invert) {
179 return !m_SelectFlags[index];
180 } else {
181 return m_SelectFlags[index];
182 }
183 }
184
185 /**
186 * Constructs a representation of the current range. Being a string
187 * representation, the numbers are based from 1.
188 *
189 * @return the string representation of the current range
190 */
191 public String toString() {
192
193 if (m_RangeStrings.size() == 0) {
194 return "Empty";
195 }
196 String result ="Strings: ";
197 Enumeration enum = m_RangeStrings.elements();
198 while (enum.hasMoreElements()) {
199 result += (String)enum.nextElement() + " ";
200 }
201 result += "\n";
202
203 result += "Invert: " + m_Invert + "\n";
204
205 try {
206 if (m_Upper == -1) {
207 throw new RuntimeException("Upper limit has not been specified");
208 }
209 String cols = null;
210 for (int i = 0; i < m_SelectFlags.length; i++) {
211 if (isInRange(i)) {
212 if (cols == null) {
213 cols = "Cols: " + (i + 1);
214 } else {
215 cols += "," + (i + 1);
216 }
217 }
218 }
219 if (cols != null) {
220 result += cols + "\n";
221 }
222 } catch (Exception ex) {
223 result += ex.getMessage();
224 }
225 return result;
226 }
227
228 /**
229 * Gets an array containing all the selected values, in the order
230 * that they were selected (or ascending order if range inversion is on)
231 *
232 * @return the array of selected values
233 * @exception RuntimeException if the upper limit of the range hasn't been defined
234 */
235 public int [] getSelection() {
236
237 if (m_Upper == -1) {
238 throw new RuntimeException("No upper limit has been specified for range");
239 }
240 int [] selectIndices = new int [m_Upper + 1];
241 int numSelected = 0;
242 if (m_Invert)
243 {
244 for (int i = 0; i <= m_Upper; i++) {
245 if (!m_SelectFlags[i]) {
246 selectIndices[numSelected++] = i;
247 }
248 }
249 }
250 else
251 {
252 Enumeration enum = m_RangeStrings.elements();
253 while (enum.hasMoreElements()) {
254 String currentRange = (String)enum.nextElement();
255 int start = rangeLower(currentRange);
256 int end = rangeUpper(currentRange);
257 for (int i = start; (i <= m_Upper) && (i <= end); i++) {
258 if (m_SelectFlags[i]) {
259 selectIndices[numSelected++] = i;
260 }
261 }
262 }
263 }
264 int [] result = new int [numSelected];
265 System.arraycopy(selectIndices, 0, result, 0, numSelected);
266 return result;
267 }
268
269 /**
270 * Creates a string representation of the indices in the supplied array.
271 *
272 * @param indices an array containing indices to select.
273 * Since the array will typically come from a program, indices are assumed
274 * from 0, and thus will have 1 added in the String representation.
275 */
276 public static String indicesToRangeList(int []indices) {
277
278 StringBuffer rl = new StringBuffer();
279 int last = -2;
280 boolean range = false;
281 for(int i = 0; i < indices.length; i++) {
282 if (i == 0) {
283 rl.append(indices[i] + 1);
284 } else if (indices[i] == last) {
285 range = true;
286 } else {
287 if (range) {
288 rl.append('-').append(last);
289 range = false;
290 }
291 rl.append(',').append(indices[i] + 1);
292 }
293 last = indices[i] + 1;
294 }
295 if (range) {
296 rl.append('-').append(last);
297 }
298 return rl.toString();
299 }
300
301 /** Sets the flags array. */
302 protected void setFlags() {
303
304 m_SelectFlags = new boolean [m_Upper + 1];
305 Enumeration enum = m_RangeStrings.elements();
306 while (enum.hasMoreElements()) {
307 String currentRange = (String)enum.nextElement();
308 int start = rangeLower(currentRange);
309 int end = rangeUpper(currentRange);
310 for (int i = start; (i <= m_Upper) && (i <= end); i++) {
311 m_SelectFlags[i] = true;
312 }
313 }
314 }
315
316
317 /**
318 * Translates a single string selection into it's internal 0-based equivalent
319 *
320 * @param single the string representing the selection (eg: 1 first last)
321 * @return the number corresponding to the selected value
322 */
323 protected int rangeSingle(String single) {
324
325 if (single.toLowerCase().equals("first")) {
326 return 0;
327 }
328 if (single.toLowerCase().equals("last")) {
329 return m_Upper;
330 }
331 int index = Integer.parseInt(single) - 1;
332 if (index < 0) {
333 index = 0;
334 }
335 if (index > m_Upper) {
336 index = m_Upper;
337 }
338 return index;
339 }
340
341 /**
342 * Translates a range into it's lower index.
343 *
344 * @param range the string representation of the range
345 * @return the lower index of the range
346 */
347 protected int rangeLower(String range) {
348
349 int hyphenIndex;
350 if ((hyphenIndex = range.indexOf('-')) >= 0) {
351 return Math.min(rangeLower(range.substring(0, hyphenIndex)),
352 rangeLower(range.substring(hyphenIndex + 1)));
353 }
354 return rangeSingle(range);
355 }
356
357 /**
358 * Translates a range into it's upper index. Must only be called once
359 * setUpper has been called.
360 *
361 * @param range the string representation of the range
362 * @return the upper index of the range
363 */
364 protected int rangeUpper(String range) {
365
366 int hyphenIndex;
367 if ((hyphenIndex = range.indexOf('-')) >= 0) {
368 return Math.max(rangeUpper(range.substring(0, hyphenIndex)),
369 rangeUpper(range.substring(hyphenIndex + 1)));
370 }
371 return rangeSingle(range);
372 }
373
374 /**
375 * Determines if a string represents a valid index or simple range.
376 * Examples: <code>first last 2 first-last first-4 4-last</code>
377 * Doesn't check that a < b for a-b
378 *
379 * @param range
380 * @return true if the range is valid
381 */
382 protected boolean isValidRange(String range) {
383
384 if (range == null) {
385 return false;
386 }
387 int hyphenIndex;
388 if ((hyphenIndex = range.indexOf('-')) >= 0) {
389 if (isValidRange(range.substring(0, hyphenIndex)) &&
390 isValidRange(range.substring(hyphenIndex + 1))) {
391 return true;
392 }
393 return false;
394 }
395 if (range.toLowerCase().equals("first")) {
396 return true;
397 }
398 if (range.toLowerCase().equals("last")) {
399 return true;
400 }
401 try {
402 int index = Integer.parseInt(range);
403 if (index > 0) {
404 return true;
405 }
406 return false;
407 } catch (NumberFormatException ex) {
408 return false;
409 }
410 }
411
412 /**
413 * Main method for testing this class.
414 *
415 * @param argv one parameter: a test range specification
416 */
417 public static void main(String [] argv) {
418
419 try {
420 if (argv.length == 0) {
421 throw new Exception("Usage: Range <rangespec>");
422 }
423 Range range = new Range();
424 range.setRanges(argv[0]);
425 range.setUpper(9);
426 range.setInvert(false);
427 System.out.println("Input: " + argv[0] + "\n"
428 + range.toString());
429 int [] rangeIndices = range.getSelection();
430 for (int i = 0; i < rangeIndices.length; i++)
431 System.out.print(" " + (rangeIndices[i] + 1));
432 System.out.println("");
433 } catch (Exception ex) {
434 System.out.println(ex.getMessage());
435 }
436 }
437}
438
439
Note: See TracBrowser for help on using the repository browser.