通过阈值列表对值列表进行分类

Classify a list of value through a list of thresholds

我有一张 <String,Double> 的地图被视为 class 确定双打列表

的门槛
HashMap<String, Double> map = new Hashmap<>();
map.put(A/B,0.7);
map.put(B/C,0.4);
map.put(C/D,0.3);
map.put(D/E,0.1);

散列的 Doubles 用作阈值以 class 验证给定的列表 double,所以我想将此映射转换为 classes A、B、C、D 的列表

Class A : from 0.7
Class B : from 0.4 to 0.7
Class C : from 0.3 to 0.4
Class D : from 0.1 to 0.3
Class E : less than 0.1

您是否知道如何将其作为一种方法执行 StringClassifyByValue(HashMap<String, Double> map, Double value){} returning 作为参数给定值的 class 对应字符串?

ِ示例:

this.StringClassifyByValue(map,0.5)不得不returnB.

一些想法:首先,你的数据结构并没有真正帮助你解决你想要解决的问题。但这正是数据结构存在的目的:为您提供有用的抽象,使您能够有效地解决 "most important" 问题。

从那里开始,我建议您首先创建 class更好 符合您的问题陈述的内容。你可以从

开始
public class Interval {

   private final double lowerBoundary;
   private final double upperBoundary;

   public Interval(double lowerBoundary, upperBoundary) {
     this.lowerBoundary = ...
   } 

   public boolean contains(double value) {
     return (value >= lowerBoundary) && (value <=upperBoundary);
   }

与其继续使用 Map<String, Double>,不如使用 List<Pair<Classification, Interval>> 之类的东西,其中:

  • Pair 可以是一个 class,它只包含两个属于一起的值(而不是使用 "generic" 对 class,您也可以创建自己的自定义值class 组合 一个 Classification 和一个 Interval).
  • Classification 表示 "class",如您的示例中的 A、B、C。关键是:为此类目的使用原始 String 对象时要小心。也许一个简单的字符串现在就可以了,但也许你以后必须进一步增强你的逻辑——然后找到 "hm, now a simple string doesn't do any more, but now I have to update a ton of places to change that".

当然:理想情况下,您可以按 "intervals" 对上述列表进行 排序。然后找到特定双精度值的 Classification 非常简单:

 for (Pair<Classification, Interval> combo : listOfPairs) {
   if (combo.getInterval().contains(value)) {
     return combo.getClassification(); // yeeha found one
   }
 }
 return "nothing found" ... or throw some kind of exception

长话短说:我无法告诉您如何最好地将您现有的地图转换到上面的成对对象列表中 - 因为我不知道大局。可以简单地 而不是 最初创建该地图,然后直接构建这样一个对象列表。

记录一下:如果该地图作为地图存在是因为有 其他,更重要的要求......那么如果你真的想继续使用,你必须仔细权衡map+list(表示 "double book-keeping"),或者如果您将上述所有逻辑放入将 Map 转换为 List 的服务中,进行查找,然后丢弃数据的这种 "other" 表示形式。

private HashMap<String, HashMap<String, Double>> getMinMaxThreshold(HashMap<String, Double> map) {

        List<Double> threholds = map.values().stream().collect(Collectors.toList());
        HashMap<String,Double >map1= this.sortByValues(map);
        List<String> keys = map1.keySet().stream().collect(Collectors.toList());

        Collections.sort(threholds);
        Collections.reverse(threholds);

        HashMap<String, HashMap<String,Double>> boudaries = new HashMap<>();


        for (int i =0;i<=threholds.size();i++){

            if(i==threholds.size()){
                HashMap<String, Double> testmap = new HashMap<>();
                testmap.put("max",threholds.get(i-1));
                testmap.put("min",0.0);
                boudaries.put(keys.get(keys.size()-1).split("/")[1], testmap);
                System.out.println(threholds.get(i-1)+" ->"+0+" : "+keys.get(keys.size()-1).split("/")[1] );
            }

            else if (i==0){
                HashMap<String, Double> testmap = new HashMap<>();
                testmap.put("max",Math.exp(1000));
                testmap.put("min",threholds.get(i));
                boudaries.put(keys.get(0).split("/")[0], testmap);
                System.out.println(Math.exp(100) +" ->"+threholds.get(i)+" : "+keys.get(0).split("/")[0] );}

            else{
                HashMap<String, Double> testmap = new HashMap<>();
                testmap.put("max",threholds.get(i-1));
                testmap.put("min",threholds.get(i));
                boudaries.put(keys.get(i).split("/")[0], testmap);
            System.out.println(threholds.get(i-1)+" ->"+threholds.get(i)+" : "+keys.get(i).split("/")[0]);}
        }

        System.err.println(boudaries);

        return boudaries;
    }
  1. “键”是一个“列表”,代表 类 A、B、C、D。
  2. thresholds是一个'List'表示的阈值。我们有 使用此阈值来设置边界。
  3. 我按值对阈值映射进行排序,以降序排列字符串,并与双阈值列表相同,使它们按相同的顺序排列。
  4. 我循环 foreach 元素的阈值。对于第一个项目,它是关于最后一个边界的,所以我将 Exp(1000) 和前一个元素作为边界。对于最后一个元素,它是关于最小值为 0 且最大值为阈值最后一个元素的边界。

  5. 我使用 split 来获取拆分数组的第一个元素,除了最后一项,我使用数组的第二个元素来匹配最后一个元素。就是这样

测试:

如果我们将这个“地图”作为输入

{ "YELLOW_DARK/RED_LIGHT" : 0.20459770114942527 , "GREEN_DARK/GREEN_LIGHT" : 0.6226151930261519 , "GREEN_LIGHT/YELLOW_LIGHT" : 0.4632936507936508 , "YELLOW_LIGHT/YELLOW_DARK" : 0.3525246305418719 , "RED_LIGHT/RED_DARK" : 0.027777777777777776}

我的代码会将其转换为:

2.6881171418161356E43 ->0.6226151930261519 : GREEN_DARK
0.6226151930261519 ->0.4632936507936508 : GREEN_LIGHT
0.4632936507936508 ->0.3525246305418719 : YELLOW_LIGHT
0.3525246305418719 ->0.20459770114942527 : YELLOW_DARK
0.20459770114942527 ->0.027777777777777776 : RED_LIGHT
0.027777777777777776 ->0 : RED_DARK

并作为 HashMap<String, HashMap<String, Double>>

返回
{GREEN_LIGHT={min=0.4632936507936508, max=0.6226151930261519}, YELLOW_DARK={min=0.20459770114942527, max=0.3525246305418719}, YELLOW_LIGHT={min=0.3525246305418719, max=0.4632936507936508}, RED_DARK={min=0.0, max=0.027777777777777776}, RED_LIGHT={min=0.027777777777777776, max=0.20459770114942527}, GREEN_DARK={min=0.6226151930261519, max=Infinity}}
{ "GREEN/LIGHT_YELLOW" : 0.5366379310344828 , "YELLOW_DARK/RED_LIGHT" : 0.18349195937745413 , "YELLOW_LIGHT/YELLOW_DARK" : 0.3571428571428571 , "RED_LIGHT/RED_DARK" : 0.08940809968847352}