/* GeoGebra - Dynamic Mathematics for Everyone http://www.geogebra.org This file is part of GeoGebra. 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. */ package org.geogebra.common.kernel.advanced; import java.util.Iterator; import org.apache.commons.math3.stat.Frequency; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.StringTemplate; import org.geogebra.common.kernel.algos.AlgoElement; import org.geogebra.common.kernel.arithmetic.MyDouble; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoList; import org.geogebra.common.kernel.geos.GeoNumeric; import org.geogebra.common.kernel.geos.GeoText; import org.geogebra.common.kernel.statistics.FrequencyGgb; import org.geogebra.common.plugin.GeoClass; public class AlgoUnique extends AlgoElement { private GeoList dataList; // input private GeoList uniqueList; // output private Frequency f; public AlgoUnique(Construction cons, String label, GeoList dataList) { this(cons, dataList); uniqueList.setLabel(label); } public AlgoUnique(Construction cons, GeoList dataList) { super(cons); this.dataList = dataList; uniqueList = new GeoList(cons); setInputOutput(); compute(); } @Override public Commands getClassName() { return Commands.Unique; } @Override protected void setInputOutput() { // make sure that x(Element[list,1]) will work even if the output list's // length is zero uniqueList.setTypeStringForXML(dataList.getTypeStringForXML()); input = new GeoElement[1]; input[0] = dataList; super.setOutputLength(1); super.setOutput(0, uniqueList); setDependencies(); // done by AlgoElement } public GeoList getResult() { return uniqueList; } @Override public final void compute() { // Validate input arguments if (!dataList.isDefined() || dataList.size() == 0) { uniqueList.setUndefined(); return; } uniqueList.setDefined(true); uniqueList.clear(); if (!(dataList.getElementType().equals(GeoClass.TEXT) || dataList.getElementType().equals(GeoClass.NUMERIC))) { for (int i = 0; i < dataList.size(); i++) { AlgoUnion.addToOutputList(uniqueList, dataList.get(i)); } return; } // Load the data into f, an instance of Frequency class if (f == null) { f = new FrequencyGgb(); } f.clear(); for (int i = 0; i < dataList.size(); i++) { if (dataList.getElementType().equals(GeoClass.TEXT)) { f.addValue(((GeoText) dataList.get(i)) .toValueString(StringTemplate.defaultTemplate)); } if (dataList.getElementType().equals(GeoClass.NUMERIC)) { f.addValue(new MyDouble(kernel, ((GeoNumeric) dataList.get(i)).getDouble())); } } // Get the unique value list if (dataList.getElementType().equals(GeoClass.TEXT)) { // handle string data Iterator<Comparable<?>> itr = f.valuesIterator(); while (itr.hasNext()) { String s = (String) itr.next(); GeoText text = new GeoText(cons); text.setTextString(s); uniqueList.add(text); } } else { // handle numeric data Iterator<Comparable<?>> itr = f.valuesIterator(); while (itr.hasNext()) { MyDouble n = (MyDouble) itr.next(); uniqueList.addNumber(n.getDouble(), this); } } } }