/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * InstanceComparator.java * Copyright (C) 2005 University of Waikato, Hamilton, New Zealand * */ package weka.core; import java.io.BufferedReader; import java.io.FileReader; import java.io.Serializable; import java.util.Comparator; /** * A comparator for the Instance class. it can be used with or without the * class label. Missing values are sorted at the beginning.<br> * Can be used as comparator in the sorting and binary search algorithms of * <code>Arrays</code> and <code>Collections</code>. * * @see Instance * @author FracPete (fracpete at cs dot waikato dot ac dot nz) * @version $Revision: 5953 $ * @see java.util.Arrays * @see java.util.Collections */ public class InstanceComparator implements Comparator<Instance>, Serializable, RevisionHandler { /** for serialization */ private static final long serialVersionUID = -6589278678230949683L; /** whether to include the class in the comparison */ protected boolean m_IncludeClass; /** * initializes the comparator and includes the class in the comparison */ public InstanceComparator() { this(true); } /** * initializes the comparator */ public InstanceComparator(boolean includeClass) { super(); setIncludeClass(includeClass); } /** * sets whether the class should be included (= TRUE) in the comparison * * @param includeClass whether to include the class in the comparison */ public void setIncludeClass(boolean includeClass) { m_IncludeClass = includeClass; } /** * returns TRUE if the class is included in the comparison */ public boolean getIncludeClass() { return m_IncludeClass; } /** * compares the two instances, returns -1 if o1 is smaller than o2, 0 * if equal and +1 if greater. The method assumes that both instance objects * have the same attributes, they don't have to belong to the same dataset. * * @param o1 the first instance to compare * @param o2 the second instance to compare * @return returns -1 if o1 is smaller than o2, 0 if equal and +1 * if greater */ public int compare(Instance o1, Instance o2) { int result; Instance inst1; Instance inst2; int classindex; int i; inst1 = (Instance) o1; inst2 = (Instance) o2; // get class index if (inst1.classIndex() == -1) classindex = inst1.numAttributes() - 1; else classindex = inst1.classIndex(); result = 0; for (i = 0; i < inst1.numAttributes(); i++) { // exclude class? if (!getIncludeClass() && (i == classindex)) continue; // comparing attribute values // 1. special handling if missing value (NaN) is involved: if (inst1.isMissing(i) || inst2.isMissing(i)) { if (inst1.isMissing(i) && inst2.isMissing(i)) { continue; } else { if (inst1.isMissing(i)) result = -1; else result = 1; break; } } // 2. regular values: else { if (Utils.eq(inst1.value(i), inst2.value(i))) { continue; } else { if (inst1.value(i) < inst2.value(i)) result = -1; else result = 1; break; } } } return result; } /** * Returns the revision string. * * @return the revision */ public String getRevision() { return RevisionUtils.extract("$Revision: 5953 $"); } /** * for testing only. takes an ARFF-filename as first argument to perform * some tests. */ public static void main(String[] args) throws Exception { Instances inst; Comparator<Instance> comp; if (args.length == 0) return; // read instances inst = new Instances(new BufferedReader(new FileReader(args[0]))); inst.setClassIndex(inst.numAttributes() - 1); // compare incl. class comp = new InstanceComparator(); System.out.println("\nIncluding the class"); System.out.println("comparing 1. instance with 1.: " + comp.compare(inst.instance(0), inst.instance(0))); System.out.println("comparing 1. instance with 2.: " + comp.compare(inst.instance(0), inst.instance(1))); System.out.println("comparing 2. instance with 1.: " + comp.compare(inst.instance(1), inst.instance(0))); // compare excl. class comp = new InstanceComparator(false); System.out.println("\nExcluding the class"); System.out.println("comparing 1. instance with 1.: " + comp.compare(inst.instance(0), inst.instance(0))); System.out.println("comparing 1. instance with 2.: " + comp.compare(inst.instance(0), inst.instance(1))); System.out.println("comparing 2. instance with 1.: " + comp.compare(inst.instance(1), inst.instance(0))); } }