Java 如何计算唯一的;“模式”;从一个数组?
我的任务是找到给定数组的模式(未指定长度)。模式定义为最唯一出现的数字。例如,数组[1.0,2.0,3.0,2.0]的模式是2.0。但是,如果该值没有唯一的数字,例如[1.0、2.0、2.0、3.0、3.0],则程序在我的程序中返回“no mode”或“Double.NaN” 我已经编写了适用于3/4测试用例的代码,但在捕获两种模式相同的情况时总是会出错Java 如何计算唯一的;“模式”;从一个数组?,java,loops,Java,Loops,我的任务是找到给定数组的模式(未指定长度)。模式定义为最唯一出现的数字。例如,数组[1.0,2.0,3.0,2.0]的模式是2.0。但是,如果该值没有唯一的数字,例如[1.0、2.0、2.0、3.0、3.0],则程序在我的程序中返回“no mode”或“Double.NaN” 我已经编写了适用于3/4测试用例的代码,但在捕获两种模式相同的情况时总是会出错 public double mode() { double modeOne = data[0]; double modeTw
public double mode() {
double modeOne = data[0];
double modeTwo = 0;
int count = 0;
int countOne = 0;
int countTwo = 0;
if(data.length == 1) { // special case: if array length is 1 the mode will always just be that value
modeOne = data[0];
return modeOne;
} // end if
for(int i = 0; i < data.length; i++) { // pulling out first value
double value = data[i];
for(int n = 0; n < data.length; n++) { // comparing first value to all other values
if (data[n] == value) {
count ++; // adding onto a count of how many of the same number there are
}
}
if(modeOne == value || modeTwo == value) { // move on if the modes already have that value
continue;
}
if(count > countOne) { // setting the max count
countTwo = countOne;
countOne = count;
modeTwo = modeOne;
modeOne = value;
}
else if(count > countTwo) { // setting second highest count
countTwo = count;
modeTwo = value;
}
} // end for
if(countOne == 1) { // if all the modes are just one
return Double.NaN;
}
if(countOne == countTwo) { // if there are two of the same modes
return Double.NaN;
}
else {
return modeOne;
}
} //end MODE
我期望“NaN”,但它返回4。但是,它适用于以下情况:
double[] data = {-5.3, 2.5, 88.9, 0, 0.0, 28, 16.5, 88.9, 109.5, -90, 88.9};
Stat stat1 = new Stat(data);
System.out.println("stat1 mode = " + stat1.mode());
预期输出为88.9,程序正确输出。因为我有心情接受一个小挑战,所以我确实编写了自己的解决方案,使用映射来计算各个值 然后检索可用的最高计数,并再次迭代映射以确定多个条目是否具有相同的最高计数,如果是,则返回NaN
public static double calculateMode(double[] numbers) {
Map<Double, Integer> lookupMap = new TreeMap<>();
for (double number : numbers) {
if (lookupMap.get(number) != null) {
lookupMap.put(number, lookupMap.get(number) + 1);
} else {
lookupMap.put(number, 1);
}
}
int max = -1;
double maxKey = Double.NaN;
for (Entry<Double, Integer> entry : lookupMap.entrySet()) {
if (entry.getValue() > max) {
max = entry.getValue();
maxKey = entry.getKey();
}
}
int foundMax = 0;
for (Entry<Double, Integer> entry : lookupMap.entrySet()) {
if (entry.getValue() == max) {
foundMax++;
}
}
if (foundMax > 1) {
return Double.NaN;
}
return maxKey;
}
产出:
Expected NaN - and was: NaN
Expected 88.90 - and was: 88.9
没有
收藏
等。。。纯硬编程:)
公共双模式(双[]数据)
{
if(data.length==1)
返回数据[0];
双温;
double[]fr=新的double[data.length];//存储频率
int=-1;
对于(int i=0;i
因此,我也感到了挑战,并在不使用集合的情况下找到了解决方案。
这不是一个很好的解决方案,但似乎有效:
public class TestMode
{
private static class NumberFrequency
{
double number;
int frequency;
}
public static double calculateMode(double[] numbers)
{
// Maybe array empty
if ((numbers == null) || (numbers.length == 0))
return Double.NaN;
// Initialize array with frequencies
NumberFrequency[] array;
int size = 0;
array = new NumberFrequency[numbers.length];
// Loop over numbers determining frequencies
for (double number : numbers)
{
// Maybe encountered before
int index;
for (index = 0; index < size; index++)
{
if (array[index].number == number)
break;
}
// Update array
NumberFrequency elm;
if (index == size)
{
elm = new NumberFrequency();
elm.number = number;
elm.frequency = 0;
array[index] = elm;
size++;
}
else
elm = array[index];
elm.frequency += 1;
} // for all numbers
// Initialize element with highest frequency
int index_highest;
int highest_freq;
int nr_occurs;
index_highest = 0;
highest_freq = array[0].frequency;
nr_occurs = 1;
// Search 'better' element
int counter;
for (counter = 1; counter < size; counter++)
{
if (array[counter].frequency > highest_freq)
{
index_highest = counter;
highest_freq = array[counter].frequency;
nr_occurs = 1;
}
else if (array[counter].frequency == highest_freq)
nr_occurs++;
}
// Return result
if (nr_occurs == 1)
return array[index_highest].number;
else
return Double.NaN;
} // calculateMode
public static void main(String[] args)
{
double[] data = {1, 2, 2, 3, 3, 4};
double[] data2 = {-5.3, 2.5, 88.9, 0, 0.0, 28, 16.5, 88.9, 109.5, -90, 88.9};
System.out.println("Expected NaN - and was: " + calculateMode(data));
System.out.println("Expected 88.90 - and was: " + calculateMode(data2)); }
} // class TestMode
公共类测试模式
{
专用静态类号频率
{
双数;
整数频率;
}
公共静态双计算器模式(双[]个数字)
{
//也许数组是空的
if((numbers==null)| |(numbers.length==0))
返回Double.NaN;
//使用频率初始化阵列
NumberFrequency[]阵列;
int size=0;
数组=新的NumberFrequency[numbers.length];
//环路数决定频率
用于(双倍数字:数字)
{
//可能以前遇到过
整数指数;
对于(索引=0;索引最高频率)
{
指数=计数器;
最高频率=阵列[计数器]。频率;
nr_=1;
}
else if(数组[计数器]。频率==最高频率)
nr_++;
}
//返回结果
如果(nr_发生==1)
返回数组[index_highest].number;
其他的
返回Double.NaN;
}//计算模式
公共静态void main(字符串[]args)
{
双[]数据={1,2,2,3,3,4};
双[]数据2={-5.3,2.5,88.9,0,0.0,28,16.5,88.9,109.5,-90,88.9};
System.out.println(“预期的NaN-和was:+calculateMode(数据));
System.out.println(“预期为88.90-was:+calculateMode(data2));}
}//类TestMode
添加一个备选方案,因为我也感到了挑战:
总体思路是在上面给出的示例之前生成一个频率阵列
[1.0, 2.0, 2.0, 3.0, 3.0]
[1, 2, 2, 2, 2]
指示相同索引的元素在输入中的次数,然后在频率数组中查找最大值,最后检查具有相同频率的所有值是否相等
public static double mode(double [] data) {
if(data == null || data.length < 1){
return Double.NaN;
}
int [] freq = new int [data.length];
for(int i = 0; i<data.length; i++){
for(int j = 0; j<data.length; j++){
if(data[i]==data[j]){
freq[i]++;
}
}
}
int max = 0;
double mode = data[0];
for(int i = 0; i<freq.length; i++){
if(freq[i]>max){
max = freq[i];
mode = data[i];
}
}
for(int i = 0; i<freq.length; i++){
if(freq[i] == max){
if(mode != data[i]){
return Double.NaN;
}
}
}
return mode;
}
公共静态双模式(双[]数据){
if(data==null | | data.length<1){
返回Double.NaN;
}
int[]freq=新的int[data.length];
对于(inti=0;i,这里是一个使用流式API的方法。但是,我采用了模式的定义,它是一个集合而不是一个数字
import org.junit.Test;
import java.util.Arrays;
import java.util.Map;
import java.util.OptionalLong;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
public class ModeTest {
private <T extends Number> Set<T> modes(T... input) {
return modes(Arrays.stream(input));
}
/**
* Calculate the modes of a numeric stream. The modes are the values that occurs most often. If no number in the
* stream is repeated, then all the numbers in the stream are modes.
*
* @param input stream of numbers
* @param <T> number type
* @return modes.
*/
private <T extends Number> Set<T> modes(Stream<T> input) {
// transform the input to a map containing the counted entries
final Set<Map.Entry<T, Long>> countedEntries = input
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet();
// Figure out the max value
final OptionalLong max = countedEntries
.parallelStream()
.mapToLong(Map.Entry::getValue)
.max();
// Handle the case where the stream was empty
if (max.isEmpty()) {
return Set.of();
}
return countedEntries
.parallelStream()
.filter(e -> e.getValue() == max.getAsLong())
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
}
@Test
public void oneMode() {
final Double[] input = new Double[]{1.0, 1.1, 1.2, 2.0, 2.0, 3.0};
assertEquals(modes(input), Set.of(2.0));
}
@Test
public void multipleModes() {
final Stream<Double> input = Stream.of(1.0, 1.1, 1.2, 2.0, 2.0, 3.0, 3.0);
assertEquals(modes(input), Set.of(2.0, 3.0));
}
@Test
public void allSingles() {
final Stream<Double> input = Stream.of(1.0, 1.1, 1.2, 2.0, 3.0);
assertEquals(modes(input), Set.of(1.0, 1.1, 1.2, 2.0, 3.0));
}
@Test
public void largeRandomSet() {
Integer[] randoms = new Integer[204800];
for (int i = randoms.length - 1; i >= 0; --i) {
randoms[i] = ThreadLocalRandom.current().nextInt(200);
}
assertFalse(modes(randoms).isEmpty());
}
@Test
public void emptyStream() {
final Stream<Double> input = Stream.of();
assertEquals(modes(input), Set.of());
}
}
import org.junit.Test;
导入java.util.array;
导入java.util.Map;
导入java.util.OptionalLong;
导入java.util.Set;
导入java.util.concurrent.ThreadLocalRandom;
导入java.util.function.function;
导入java.util.stream.collector;
导入java.util.stream.stream;
导入静态org.junit.Assert.assertEquals;
导入静态org.junit.Assert.assertFalse;
公共类模式测试{
专用设置模式(T…输入){
返回模式(数组、流(输入));
}
/**
*计算数字流的模式。模式是最常出现的值。如果
*流被重复,那么流中的所有数字都是模式。
*
*@param数字输入流
*@param编号类型
*@返回模式。
*/
专用设置模式(流输入){
//将输入转换为包含计数项的映射
最终设置countedEntries=输入
[1.0, 2.0, 2.0, 3.0, 3.0]
[1, 2, 2, 2, 2]
public static double mode(double [] data) {
if(data == null || data.length < 1){
return Double.NaN;
}
int [] freq = new int [data.length];
for(int i = 0; i<data.length; i++){
for(int j = 0; j<data.length; j++){
if(data[i]==data[j]){
freq[i]++;
}
}
}
int max = 0;
double mode = data[0];
for(int i = 0; i<freq.length; i++){
if(freq[i]>max){
max = freq[i];
mode = data[i];
}
}
for(int i = 0; i<freq.length; i++){
if(freq[i] == max){
if(mode != data[i]){
return Double.NaN;
}
}
}
return mode;
}
import org.junit.Test;
import java.util.Arrays;
import java.util.Map;
import java.util.OptionalLong;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
public class ModeTest {
private <T extends Number> Set<T> modes(T... input) {
return modes(Arrays.stream(input));
}
/**
* Calculate the modes of a numeric stream. The modes are the values that occurs most often. If no number in the
* stream is repeated, then all the numbers in the stream are modes.
*
* @param input stream of numbers
* @param <T> number type
* @return modes.
*/
private <T extends Number> Set<T> modes(Stream<T> input) {
// transform the input to a map containing the counted entries
final Set<Map.Entry<T, Long>> countedEntries = input
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet();
// Figure out the max value
final OptionalLong max = countedEntries
.parallelStream()
.mapToLong(Map.Entry::getValue)
.max();
// Handle the case where the stream was empty
if (max.isEmpty()) {
return Set.of();
}
return countedEntries
.parallelStream()
.filter(e -> e.getValue() == max.getAsLong())
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
}
@Test
public void oneMode() {
final Double[] input = new Double[]{1.0, 1.1, 1.2, 2.0, 2.0, 3.0};
assertEquals(modes(input), Set.of(2.0));
}
@Test
public void multipleModes() {
final Stream<Double> input = Stream.of(1.0, 1.1, 1.2, 2.0, 2.0, 3.0, 3.0);
assertEquals(modes(input), Set.of(2.0, 3.0));
}
@Test
public void allSingles() {
final Stream<Double> input = Stream.of(1.0, 1.1, 1.2, 2.0, 3.0);
assertEquals(modes(input), Set.of(1.0, 1.1, 1.2, 2.0, 3.0));
}
@Test
public void largeRandomSet() {
Integer[] randoms = new Integer[204800];
for (int i = randoms.length - 1; i >= 0; --i) {
randoms[i] = ThreadLocalRandom.current().nextInt(200);
}
assertFalse(modes(randoms).isEmpty());
}
@Test
public void emptyStream() {
final Stream<Double> input = Stream.of();
assertEquals(modes(input), Set.of());
}
}