【问题标题】:Finding a value against all values in a HashMap针对 HashMap 中的所有值查找一个值
【发布时间】:2016-01-23 22:13:12
【问题描述】:

好的,所以我有一个 HashMap,我正在尝试遍历地图并检查其他节点以查看它们的值是否重叠。

例如: {job1=[[16, 18], [21, 23]], job2=[[16, 17]] [16,18] 和 [16,17] 有重叠。

在我的 Node 类中,它需要一个 NumberPairs 列表,而我的 NumberPairs 类需要一对数字(整数)。无论如何,我遇到的问题是我不知道如何相互检查键值......有什么想法吗?

目前为止

for (Map.Entry<String, Node> entry : myVertices.entrySet())
{   

//do stuff

}

【问题讨论】:

    标签: java for-loop graph hashmap overlap


    【解决方案1】:

    假设NodeNumberPair 的结构如下:

    public class Node {
        List <NumberPair> numbers = new ArrayList<>();
        // Implementation
    }
    
    public class NumberPair {
        int x, y;
        // ctor, getters, setters, etc
    }
    
    Map <String, Map<String, Integer>> returnOverlaps(Map <String, Node> myVertices) {
        Map <String, Map<String, Integer> > overlaps = new HashMap<>();
    
        for (Map.Entry<String, Node> entry : myVertices.entrySet())
        {   
            for (Map.Entry<String, Node> entry2 : myVertices.entrySet()) {
                compare(entry, entry2, overlaps);                  
            }
        }
      return overlaps;
    }
    
    void compare (Map.Entry <String, Integer> entry1, Map.Entry <String, Integer> entry2, Map <String, Map<String, Integer>> overlaps) {
      String key1 = entry1.getKey();
      Map <String, Integer> map = overlaps.get(key1);          
      if (map == null)
          map = new HashMap<>();
    
      String key2 = entry2.getkey();
      Node node1 = entry1.getValue();
      Node node2 = entry2.getValue();
    
      if (key1.equals(key2)) {
        // self         
        map.put(key1, node1.getNumbers().size());            
      }
      else {
        map.put(key2, 0);
        for (NumberPair x : node1.getNumbers()) {
          for (NumberPair y : node2.getNumbers()) {
            if (x.first() == y.first()) {              
                // Crude brute force compare, I like 'Zoran Regvart''s approach above of sorting and comparing upper/lower bounds.
                map.put(key2, map.get(key2) + 1 );
            }
          }
        }
      }
    
     overlaps.put(key1, map);          
     }
    

    有点复杂,这是overlaps 的样子。

    它将每个 jobName 映射到一个 map,其中包含其他 jobNames 以及与它们共享的重叠数

    如果你有:

    job1=[[16, 18], [21, 23]], job2=[[16, 17]], 
    job3= [[20, 21]], job4= [[21, 29], [20, 24]], [16, 2]]
    

    overlaps 看起来像

    job1 -> [job1 = 1], [job2 = 1], [job3 = 0], [job4 = 2]
    job2 -> [job1 = 1], [job2 = 1], [job3 = 0], [job4 = 2]
    job3 -> [job3 = 1], [job2 = 0], [job1 = 0], [job4 = 1]
    job4 -> [job3 = 1], [job2 = 0], [job1 = 1], [job4 = 3]
    

    如果您想检查 job3 和 job4 共享多少重叠,您会这样做

    (overlaps.get("job3")).get("job4");
    

    我没有测试过这个,也没有优化过(它不能避免多余的工作,例如,如果你已经发现 job1 和 job3 的重叠,你不应该为 job3 和 job1 .) 似乎是一个有趣的问题,所以我想我会试一试:)

    【讨论】:

      【解决方案2】:

      首先定义我们的重叠逻辑,这可以很简单:

      private static boolean overlaps(final NumberPairs first, final NumberPairs second) {
          final boolean before = first.end < second.start;
          final boolean after = first.start > second.end;
      
          return !before && !after;
      }
      

      接下来遍历所有条目及其所有对以查找重叠条件是否匹配。这样做的非常未优化的方法是:

      for (final Map.Entry<String, Node> entry : myVertices.entrySet()) {
          final Node entryValue = entry.getValue();
      
          for (final Map.Entry<String, Node> candidate : myVertices.entrySet()) {
              if (entry == candidate) {
                  continue; // entry will overlap with itself
              }
      
              final Node candidateValue = candidate.getValue();
      
              for (final NumberPairs entryPair : entryValue.pairs) {
                  for (final NumberPairs candidatePair : candidateValue.pairs) {
                      if (overlaps(entryPair, candidatePair)) {
                          System.out.printf("%s overlaps with %s in the pairs %s and %s\n", entry.getKey(), candidate.getKey(), entryPair, candidatePair);
                      }
                  }
              }
          }
      }
      

      对于少量的节点和节点对,这已经足够了,但对于大量的值,interval tree structure 会更好。

      【讨论】:

      • 干得好!在过去的半个小时里,我自己一直在努力想出一些东西。
      • 谢谢!在单独的方法中指定重叠确实是个好主意,如果我使用区间树结构会比上面更有效吗?
      • @Josh123 是的,在这个实现中它将是 O(log n + m) vs O(n^2*m)
      • @ZoranRegvart 我决定实现区间树结构。它确实在 wiki 中说“但是,对于任意重叠的间隔,没有办法比较插入树的两个间隔,因为按起点或终点排序的顺序可能不同。”,这仍然是可能的吗? ?我将如何实施这个
      • @Josh123 我喜欢你的热情,我建议你坚持使用嵌套的 for 循环解决方案,直到你需要优化。处理一些涉及的数据结构和算法可能具有挑战性。您所指的引用在“朴素方法”标题下,它解释了为什么区间树最适合此类问题,而不是说它不适合。
      【解决方案3】:

      您可以使用 Map 的 containsValue() 方法来检查元素。我假设 Node 类和它们的 setter 方法来正确解释。

       HashMap map= new HashMap();
       Node obj = new Node();
       node.setFirst(10);
       node.setLast(20);
       map.put("First Entry",node);
       int value = 16;// assuming to find in map
      
      for (Map.Entry<String, Node> entry : myVertices.entrySet())
      {   
        Node node= entry.getValue();
        if(node.getFirst()==value){
      
          System.out.println("Value found");
          //do other stuff
         break;
        }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-31
        • 2021-01-28
        • 1970-01-01
        • 1970-01-01
        • 2020-09-16
        • 1970-01-01
        • 2016-06-29
        • 1970-01-01
        相关资源
        最近更新 更多