【问题标题】:Validate String hierarchy in Java在 Java 中验证字符串层次结构
【发布时间】:2020-06-25 08:49:35
【问题描述】:

我有一个地图,它可以有键:A, B, C, D, E, F 或它的子集

其中,A, B, C and D是一组按相同顺序属于某个层次结构的字符串:A -> B -> C -> D

如果地图包含有效的层次结构,我需要检查HashMap。以哪个顺序映射存储数据无关紧要。我不关心订单,也不会检查地图内的订单。

如果地图包含其中任何一个,则将其视为有效层次结构:

A or
A, B or // A and B can be in any order
A, B, E or // as E is not in the group, so doesn't matter
A, B, C or // these can be in any order in map.
A, B, C, D or

如果mapA, B, and D但没有C,则视为无效。

我可以添加多个if else 检查,但这会使代码混乱。有什么优雅的方式来做这个检查吗?

编辑: 我已经实现了以下逻辑:


// order contains strings in order: { A, B, C, D}
private boolean isHierarchyComplete(Map<String, Object> map, String[] order) {

    // lastIndexFound, this will give the last index of string found in hierarchy that is continous and breaks out once the path is broken
    int lastIndexFound = -1;
    for (String str : order) {
      if (map.containsKey(str)) {
        lastIndexFound++;
      } else {
        break;
      }
    }

    // if nothing found from path
    if (lastIndexFound == -1) {
      return false;
    }
    
    // if all found from path
    if (lastIndexFound == order.length - 1) {
      return true;
    }
    // now check after lastIndexFound if there are any values from hierarchy,
    // if present return false
    for (int index = lastIndexFound + 1; index < order.length; index++) {
      if (map.containsKey(order[index])) {
        return false;
      }
    }

    return true;
  }

【问题讨论】:

  • 请注意,常规 Java HashMap 的键是 not 有序的,这意味着如果键 ABC 存在,则迭代键可以以任何顺序返回它们。
  • 这样的? if (!map.contains("A") || !map.contains("B") || !map.contains("C") || !map.contains("D")) invalid else valid
  • @TimBiegeleisen 是的地图不保留顺序。我不在乎什么地图顺序地图保存数据。我想检查我提到的字符串组中是否存在 Map 中的所有值。
  • 连我都不明白投反对票的原因?因为我觉得这个问题很清楚。点赞
  • 如果您需要支持有限的、固定的和已知的密钥集,请考虑将密钥包装到enum 并使用EnumMap。它将防止您使用不正确的密钥 - 然后密钥类型将确保正确性。

标签: java predicate


【解决方案1】:

我认为可以通过以下方式解决问题(工作演示),

import java.util.HashMap;

public class MyClass {
    public static void main(String args[]) {
        String[] hierarchy = {"A","B","C","D"};
        
        //Test case 1: false
        HashMap<String,String> map = new HashMap<String,String>();
        map.put("A","#");
        map.put("D","#");
        isValidMap(map,hierarchy);
        map = new HashMap<String,String>();
        
        //Test case 2: true
        map = new HashMap<String,String>();
        map.put("A","#");
        map.put("B","#");
        isValidMap(map,hierarchy);
        map = new HashMap<String,String>();
        
        //Test case 3: true
        map = new HashMap<String,String>();
        map.put("E","#");
        map.put("F","#");
        isValidMap(map,hierarchy);
        map = new HashMap<String,String>();
        
        //Test case 4: true
        map = new HashMap<String,String>();
        map.put("A","#");
        map.put("E","#");
        isValidMap(map,hierarchy);
        map = new HashMap<String,String>();
        
        //Test case 5: true
        map = new HashMap<String,String>();
        map.put("A","#");
        map.put("B","#");
        map.put("C","#");
        isValidMap(map,hierarchy);
        map = new HashMap<String,String>();
        
        //Test case 6: true
        map = new HashMap<String,String>();
        map.put("A","#");
        map.put("B","#");
        map.put("E","#");
        isValidMap(map,hierarchy);
        map = new HashMap<String,String>();
        
        //Test case 7: false
        map = new HashMap<String,String>();
        map.put("A","#");
        map.put("D","#");
        map.put("E","#");
        isValidMap(map,hierarchy);
        map = new HashMap<String,String>();
        
    }
    
    public static void isValidMap(HashMap<String,String> map, String[] hierarchy){
        boolean checkShouldBePresent = true;
        boolean finalAns = true;
        boolean changed = false;
        boolean checked = false;
        for(int i=0;i<hierarchy.length;i++){
            String s = hierarchy[i];
            
            boolean finalAnsPrev = finalAns;
            finalAns = finalAns && !changed?map.keySet().contains(s):!map.keySet().contains(s);
            
            
            if(finalAnsPrev!=finalAns && !checked){
                changed = true;
                finalAns = true;
                checked = true;
            }
        }
        
        System.out.println(finalAns);
    }
}

上面的主要逻辑在isValidMap方法中。

说明:

解决问题的逻辑如下,

我们应该从顶部开始逐个遍历层次结构元素,并检查它是否存在于给定的map 键集中。当我们发现层次结构中的一个元素在地图中丢失时,以下所有元素都不应该出现。

例如,

String[] hierarchy = {"A","B","C","D"};

//keyset = set of {"A", "B", "E"}. The truth list of the hierarchy elements pertaining to whether they are present in the keyset or not is,
[A:TRUE,B:TRUE,C:FALSE,D:FALSE]     ... (1)

//keyset = set of {"G", "F", "E"}. The truth list of the hierarchy elements pertaining to whether they are present in the keyset or not is,
[A:FALSE,B:FALSE,C:FALSE,D:FALSE].  ... (2)

//keyset = set of {"A", "B", "D"}. The truth list of the hierarchy elements pertaining to whether they are present in the keyset or not is,
[A:TRUE,B:TRUE,C:FALSE,D:TRUE].  ... (3)

在上面的示例 (3) 中,请注意真值如何从 TRUE 变为 FALSE,然后再变为 TRUE。在所有这些情况下,我们会说地图键集不服从我们的层次结构。

时间复杂度也应该是O(n),其中n是层次数组的长度。

【讨论】:

  • 谢谢,和我写的差不多。我已经用我的实现编辑了我的答案。你的看起来更干净。
  • 虽然有一个案例失败了。如果没有从层次结构组传递字符串。它打印真实。应该是假的。
【解决方案2】:

所以基本上你有某些键不能出现,除非它们的“父”键也在那里:

String[] keyHierarchy = "A B C D".split(" ");

你正在实现类似于

boolean hasValidKeysAsPerHierarchy(Set<String> keySet, ArrayList<String> hierarchy) { ... }

请注意,您可以从Map&lt;String, Anything&gt; mm.keySet() 获取一组密钥;您还可以通过将String[] a 转换为List&lt;String&gt; l Arrays.asList(a)

这可以通过首先找到 keySet 中的最后一个层次键,然后检查是否存在所有其他层次较小的键来实现。

boolean hasValidKeysAsPerHierarchy(Set<String> keySet, List<String> hierarchy) {
    int lastHKPos = -1;
    for (String k : keySet) {
        lastHKPos= Math.max(hierarchy.indexOf(k), lastHKPos);
    }
    // now, we need to find all hierarchy-keys from 0 to lastHKPos, exclusive
    for (int i=0; i<lastHKPos; i++) {
        String hKey = hierarchy.get(i);
        if ( ! keySet.contains(hKey)) return false; // missing hierarchy-key!
    }
    return true; // no missing hierarchy-keys
}

如果层次结构的大小(我们称之为h)非常大,您可以通过构建辅助Map&lt;String,Integer&gt; 来将层次结构键映射到它们,从而加快第一个for 循环从O(n * h)O(n * log(h))在层次结构中的位置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多