【问题标题】:How to compare 'list of string' with 'enum string values' to return maximum match?如何将“字符串列表”与“枚举字符串值”进行比较以返回最大匹配?
【发布时间】:2021-12-01 17:15:21
【问题描述】:

当前代码发送List<String>,但如果所有值都匹配则返回枚举

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public enum Rara {
    MA_ON("ST"),
    MA_MAN("ST", "YS"),
    MA_IP("ST", "YS", "IC"),
    CODE("RC");

    Rara(String... codes) {
        this.codes = List.of(codes);
    }

    private List<String> codes;

    public static Optional<Rara> getValue(List<String> values){
        return Arrays.stream(values())
                .filter(rara -> rara.codes.containsAll(values))
                .findFirst();
    }
}

public class Main {
  public static void main(String args[]){
    System.out.println(Rara.getValue(Arrays.asList("ST", "YS")));  
          // Optional[MA_MAN]

    System.out.println(Rara.getValue(Arrays.asList("ST")));  
          // Optional[MA_ON]
  }
}

但现在的要求是,如果我们得到 List,那么应该返回最大匹配枚举

System.out.println(Rara.getValue(Arrays.asList("ST", "YS", "IC", "BLABLA")));  
 //Should return MA_IP
System.out.println(Rara.getValue(Arrays.asList("ST", "Bla", "Blabla", "BLABLA")));  
//Should return MA_ON

注意:如果 ST 和 RC 或任何冲突,我们需要选择第一个。 (像ST、RC我们可以选择MA_ON)

谁能建议如何在 getValue 中实现相同的枚举? (如果我添加包含,则代替 containsALL 则它不起作用。不确定它是否需要一些 maxmatch 等)

【问题讨论】:

  • Arrays.asList("ST", "RC") 这样的参数呢?这种情况可能吗?如果是,结果应该是什么(MA_ONCODE 或其他)?
  • @Pshemo:是的,我问过这个,然后他们说选择第一个

标签: java enums


【解决方案1】:

如果我正确理解了您的问题,您所需要的就是

  • 知道codesvalues 有多少常用字符串(对于每个枚举)
  • 过滤掉没有共同元素的那些
  • 选择一个公共元素数量最多的一个(或者在有很多最大值的情况下第一个)

为了简化我们的工作,我们可以创建帮助方法来仅查找两个列表中的共同元素。它看起来像(我假设您的列表将只有独特的元素)

private static List<String> commonElements(List<String> list1, List<String> list2) {
    List<String> common = new ArrayList<>(list1); // to avoid modifying `list1`
    common.retainAll(list2); // leaves in `common` only elements from `list2`
    return common;
}

这样我们就可以

  • 将每个枚举映射到包含enum, amountOfCommonElements 的对(我们可以使用Map.entry 来创建对),
  • amountOfCommonElements 为 0 的过滤器对,
  • 选择最大amountOfCommonElements的配对
  • 仅从该对中获取 enum

演示:

enum Rara {
    MA_ON("ST"),
    MA_MAN("ST", "YS"),
    MA_IP("ST", "YS", "IC"),
    CODE("RC");

    Rara(String... codes) {
        this.codes = List.of(codes);
    }

    private List<String> codes;

    private static List<String> commonElements(List<String> list1, List<String> list2) {
        List<String> common = new ArrayList<>(list1); // to avoid modifying `list1`
        common.retainAll(list2); // leaves in `common` only elements from `list2`
        return common;
    }

    public static Optional<Rara> getValue(List<String> values){
        return Arrays.stream(values())
                .map(en -> Map.entry(en, commonElements(en.codes, values).size()))
                .filter(entry -> entry.getValue()>0)
                .max(Comparator.comparing(Map.Entry::getValue))
                .map(Map.Entry::getKey);
    }

}

 class Main {
    public static void main(String args[]){
        System.out.println(Rara.getValue(Arrays.asList("ST", "YS")));
        // Optional[MA_MAN]

        System.out.println(Rara.getValue(Arrays.asList("ST")));
        // Optional[MA_ON]

        System.out.println(Rara.getValue(Arrays.asList("ST", "RC")));
        // Optional[MA_ON]

        System.out.println(Rara.getValue(Arrays.asList("STB", "RCC")));
        //Optional.empty
    }
}

【讨论】:

  • 它说:无法推断 map(Function super T,? extends R>) 的类型参数
  • 您的 Java 版本是多少?在 Java 14 和 16 上进行了测试(未安装其他版本)。
  • Java 12 似乎也在工作ideone.com/SE80zq
  • 其实是 Java 11
  • 在 Java 11 上运行良好
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多