1

I have no reputation for a comment on @PeterLawrey's answer:Random weighted selection in Java. It is good. But now I call next() get a result as A and want to remove weight for A from map to avoid to get A again. How can I deal with it?

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
kinglao
  • 151
  • 9

1 Answers1

0

You can simply change this line, in PeterLawrey's solution

public E next() {
    double value = random.nextDouble() * total;
    return map.higherEntry(value).getValue();
}

to

public E next() {
    double value = random.nextDouble() * total--;
    return map.remove(higherKey(value));
}

cause remove() returns the associated value after removing

Alternatively, if you need to remove elements after choosing you can use another solution. Add all the elements into a 'LinkedList', each element must be added as many times as it weight is, then use Collections.shuffle() which, according to JavaDoc

Randomly permutes the specified list using a default source of randomness. All permutations occur with approximately equal likelihood.

Finally, get and remove elements using pop() or removeFirst()

Map<String, Integer> map = new HashMap<String, Integer>() {{
    put("Five", 5);
    put("Four", 4);
    put("Three", 3);
    put("Two", 2);
    put("One", 1);
}};

LinkedList<String> list = new LinkedList<>();

for (Map.Entry<String, Integer> entry : map.entrySet()) {
    for (int i = 0; i < entry.getValue(); i++) {
        list.add(entry.getKey());
    }
}

Collections.shuffle(list);

System.out.println("Size: " + list.size());
int size = list.size();
for (int i = 0; i < size; i++) {
    System.out.println(list.pop());
}

System.out.println("Size: " + list.size());
Yuri H
  • 680
  • 5
  • 12
  • @kinglao Was my answer helpful? Could you choose it as the correct one? – Yuri H Jun 06 '17 at 12:38
  • I think just remove can not work. Because the `total` field should change too – kinglao Jun 07 '17 at 02:11
  • @kinglao Definitely, it should be changed too according to program logic. Maybe, the second solution will be more suitable for your purposes. – Yuri H Jun 07 '17 at 07:45