I want to pick a random element from three different lists. But I want to pick it with different probabilities. I want to have these probabilites:
50% for `list_1`
35% for `list_2`
15% for `list_3`
Based on user input the picked item will be removed from the list and then goes back into one of the three lists. Then a new item gets picked. The problem is, that one or two of these lists can be empty and then it should just pick an element from the lists that are not empty. And I don't want to have the same item picked twice in a row. I tried it with generating a random number between 0 and 1 and based on the result I pick an item from one of the lists, but I always had to check if the list was empty and if so I had to call the method again. I guess there is a better way to do this. Can somebody help me?
Here is my code:
Random random = new Random();
double number = Math.random();
if (number <= 0.5) {
if (!list1.isEmpty()) {
item = list1.get(random.nextInt(list1.size()));
}
} else if (number > 0.5 && number <= 0.85) {
if (!list2.isEmpty()) {
item = list2.get(random.nextInt(list2.size()));
}
} else if (number > 0.85 && number <= 1) {
if (!list3.isEmpty()) {
item = list3.get(random.nextInt(list3.size()));
}
}
But the problem here is, that if the list which would be selected is empty, I get no item and I need to recall that method (multiple times).
CodePudding user response:
private static List<String> list1;
private static List<String> list2;
private static List<String> list3;
public static void main(String[] args) {
list1 = new ArrayList<>();
list1.add("1");
list1.add("2");
list2 = new ArrayList<>();
list2.add("3");
list2.add("4");
list2.add("5");
list3 = new ArrayList<>();
list3.add("6");
list3.add("7");
list3.add("8");
list3.add("9");
Random r = new Random();
int p = r.nextInt(100);
if (p < 50){ // 50%
p = r.nextInt(list1.size());
System.out.println("list 1 : " list1.get(p));
addToAnotherList(list1, p);
}
else if (p < 85){ // 35%
p = r.nextInt(list2.size());
System.out.println("list 2 : " list2.get(p));
addToAnotherList(list2, p);
} else { // 15%
p = r.nextInt(list3.size());
System.out.println("list 3 : " list3.get(p));
addToAnotherList(list3, p);
}
}
private static void addToAnotherList(List<String> originalList, int i) {
if (originalList.size() != 1) {
String toAdd = originalList.get(i);
originalList.remove(i);
Random r = new Random();
int p = r.nextInt(2);
if (p == 0) {
list1.add(toAdd);
} else if (p == 1) {
list2.add(toAdd);
} else {
list3.add(toAdd);
}
}
}
CodePudding user response:
Add these 2 private static methods:
private static List getOrGiveAnother(final List... lists) throws NoSuchElementException {
for (var list : lists) {
if(!list.isEmpty()) return list;
}
throw new NoSuchElementException();
}
private static Object randomValueFromList(final List list, final Random randomizer) {
return list.get(randomizer.nextInt(list.size()));
}
Use them like this:
Random random = new Random();
double number = Math.random();
try {
if (number <= 0.5) {
randomValueFromList(getOrGiveAnother(list1, list2, list3), random);
} else if (number > 0.5 && number <= 0.85) {
randomValueFromList(getOrGiveAnother(list2, list3, list1), random);
} else if (number > 0.85 && number <= 1) {
randomValueFromList(getOrGiveAnother(list3, list1, list2), random);
}
} catch (NoSuchElementException e) {
//if you fall here all lists were empty : do something to handle this case
}