5

For each key in a Guava Multimap I need to take the corresponding values and make pairs with them that are not dependent on order.Uniqueness of pairs are not dependent on order for make pairs inside of key. [A,B] = [B,A]. If the pair [B,A] is found in another key then this should treated as another pair. I don't know how iterate the values so I can print out pairs that aren't dependent on order. I'm not sure how to index this either. For arrays, I could just use a double loop.

Here is an example Multimap:

BE0004429: [DB00515, DB00951, DB01582]
BE0000059: [DB00603, DB01285]
BE0001052: [DB00366, DB00472, DB00856, DB01104, DB01149]

I want to take that data and change it to this format. Look carefully, I'm trying to take the values of each key and make pairs.

I want take the first value in the each key and pair it up with the other values. Take the second value and pair it with the value after. Until there no more unique pairs.

DB00515, DB00951
DB00515, DB01582
DB01582, DB00951

DB00603, DB01285

DB00366, DB00472
DB00366, DB00856
DB00366, DB01104
DB00366, DB01149
DB00472, DB00856
DB00472, DB01104
DB00472, DB01149
DB00856, DB01104
DB00856, DB01149
DB01104, DB01149
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user3590149
  • 1,525
  • 7
  • 22
  • 25
  • Can you format this better? – Anubian Noob May 06 '14 at 00:06
  • @AnubianNoob Does that look better? – user3590149 May 06 '14 at 00:09
  • 1
    Yup, thanks. I still don't understand how you get from one dataset to the other, but that might be just me. – Anubian Noob May 06 '14 at 00:12
  • I'm trying to take the first dataset which is what i have in the multimap and then make the second dataset. – user3590149 May 06 '14 at 00:22
  • I formatted again. I hope that help to make it more clear. – user3590149 May 06 '14 at 00:25
  • Guava MultiMap get method returns Collection. Your snippet assumes it is a String. Does this compile? – krishnakumarp May 06 '14 at 00:33
  • I'm not familiar with `MutliMap`s so I have no idea how you go between the two datasets... However, your question looks clear. – Anubian Noob May 06 '14 at 00:33
  • Yes it compiles. I print out to a file the first data set. To make the second data set, I copy and paste it to show you what I'm trying to achieve. SO I take the first value to start the pairing after it pairs with every other value then I make the second value pair up with any other values that haven't already made a unique pair. – user3590149 May 06 '14 at 01:08
  • If you could provide an [SSCCE](http://www.sscce.org/) we could run, we'd likely be able to answer your question in seconds. – dimo414 May 06 '14 at 01:12
  • Has any of edits made it clearer? I can give you the code not a problem. But all that gives you is the mutltmap I already have. I trying to figure how get data in multimap to the format of that other dataset. – user3590149 May 06 '14 at 01:17
  • @user3590149 It was not clear to me that the first block *was* a Multimap. I have reformatted your question in a way that makes sense to me, please look over it and make sure it's still what you're looking for, I'll update my answer. – dimo414 May 06 '14 at 01:24
  • Thank you. That seems to be more clear. – user3590149 May 06 '14 at 01:52

3 Answers3

6

I wrote this answer before the question was updated to more clearly describe the desired behavior, however I suspect this answer will still help some people who stumble on this question trying to understand different ways to iterate over a Multimap, so I'm leaving this answer here for posterity. See my other answer for what OP was actually looking for.


Suppose we start with the following Multimap:

Multimap<String, Integer> map = new ImmutableSetMultimap.Builder<String, Integer>()
                                .put("one", 1)
                                .putAll("several", 1, 2, 3)
                                .putAll("many", 1, 2, 3, 4, 5)
                                .build();

We can print it's contents several ways, let's try them:

  1. As a raw string:

     map.toString()
    
    {one=[1], several=[1, 2, 3], many=[1, 2, 3, 4, 5]}
    
  2. As a collection of key => collection pairs, with unique keys:

     for(String key : map.keySet()) {
       System.out.println(key+": "+map.get(key));
     }
    
     // OR with the asMap() view
    
     for(Entry<String,Collection<Integer> e : map.asMap().entrySet()) {
       System.out.println(e.getKey()+": "+e.getValue());
     }
    
    one: [1]
    
     several: [1, 2, 3]
     many: [1, 2, 3, 4, 5]
    
  3. As a collection of key => value pairs, with duplicate keys (and possibly values, if it's a ListMultimap):

     for(Entry<String, Integer> e : map.entries()) {
       System.out.println(e.getKey()+": "+e.getValue());
     }
    
    one: 1
    
     several: 1
     several: 2
     several: 3
     many: 1
     many: 2
     many: 3
     many: 4
     many: 5
    
  4. As a collection of values, without concern for their keys:

     for(Integer v : map.values()) {
       System.out.println(v);
     }
    
    1
    
     1
     2
     3
     1
     2
     3
     4
     5
    

Those are generally the ways you'd work with a Multimap. You say you're trying to "print out pairs that aren't dependent on order" - it's unclear to me what that means, but if you're saying you want the output of option 3 to be in an arbitrary order, you could write your strings to a list, then shuffle it, like so:

List<String> pairs = new ArrayList<>();
for(Entry<String, Integer> e : map.entries()) {
  pairs.add(e.getKey()+": "+e.getValue());
}
Collections.shuffle(pairs);
for(String s : pairs) {
  System.out.println(s);
}

This would print your Multimap's contents as pairs in arbitrary order.

dimo414
  • 47,227
  • 18
  • 148
  • 244
  • Uniqueness of pairs are not dependent on order for make pairs inside of key. [A,B] = [B,A]. If the pair [B,A] is found in another key then this should treated as another pair. – user3590149 May 06 '14 at 01:13
5

There's two parts to this question, now that I understand it, and really the fact that you're working with Multimaps isn't very important. It's valuable to try to break problems into its component parts; when you do the problems often become clearer, even trivial seeming.

  1. How do I print successive pairs from a collection?

    We need to define a function which will take a Collection (this will let us work with arbitrary Multimaps), and generate your pairs:

    public static <V> List<String> genPairs(Collection<V> col) {
      List<V> ls = ImmutableList.copyOf(col);
      List<String> ret = new ArrayList<>();
    
      for (int i = 0; i < ls.size()-1; i++) {
        for (int j = i+1; j < ls.size(); j++) {
          ret.add(ls.get(i)+", "+ls.get(j));
        }
      }
    
      return ret;
    }
    

    Demo:

    for(String pair : genPairs(ImmutableList.of(1,2,3))) {
      System.out.println(pair);
    }
    
    1, 2
    1, 3
    2, 3
    
  2. How do I print successive pairs from the values of a Multimap?

    This part's easy, you just loop over the value collections and call the above function:

    for(Collection<String> col : multimap.asMap().values()) {
      for(String pair : genPairs(col)) {
        System.out.println(pair);
      }
      System.out.println();
    }
    
dimo414
  • 47,227
  • 18
  • 148
  • 244
  • I think this on the right, its going take sec understand. I just little hesitate on what you mean by successive pairs because I sill need to make sure I collect all unique pairs. – user3590149 May 06 '14 at 01:57
  • @user3590149 I added some example output. The code in the function does what you describe, "take the first value in the each key and pair it up with the other values. Take the second value and pair it with the value after." – dimo414 May 06 '14 at 02:07
1

Hope this helps...

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;

public class GuavaSample {

    public static void main(String[] args) {
        Multimap<String, String> multiMap = ArrayListMultimap.create();
        multiMap.put("BE0004429", "DB00515");
        multiMap.put("BE0004429", "DB00951");
        multiMap.put("BE0004429", "DB01582");

        multiMap.put("BE0000059", "DB00603");
        multiMap.put("BE0000059", "DB01285");

        multiMap.put("BE0001052", "DB00366");
        multiMap.put("BE0001052", "DB00472");
        multiMap.put("BE0001052", "DB00856");
        multiMap.put("BE0001052", "DB01104");
        multiMap.put("BE0001052", "DB01149");

        for (String key : multiMap.keySet()) {
            List<String> list = (List<String>) multiMap.get(key);
            for (int i = 0; i < list.size(); i++) {
                for (int j = i + 1; j < list.size(); j++) {
                    System.out.println(list.get(i) + "," + list.get(j));
                }
            }
            System.out.println();
        }
    }

}
krishnakumarp
  • 8,967
  • 3
  • 49
  • 55