Выбор случайного элемента из набора - PullRequest
167 голосов
/ 24 сентября 2008

Как выбрать случайный элемент из набора? Я особенно заинтересован в выборе случайного элемента из HashSet или LinkedHashSet в Java. Решения для других языков также приветствуются.

Ответы [ 33 ]

1 голос
/ 19 июля 2018

В Java 8:

static <E> E getRandomSetElement(Set<E> set) {
    return set.stream().skip(new Random().nextInt(set.size())).findFirst().orElse(null);
}
1 голос
/ 24 сентября 2008

Поскольку вы сказали "Решения для других языков также приветствуются", вот версия для Python:

>>> import random
>>> random.choice([1,2,3,4,5,6])
3
>>> random.choice([1,2,3,4,5,6])
4
1 голос
/ 08 декабря 2014

Это идентично принятому ответу (Хот), но с удаленными ненужными переменными size и i.

    int random = new Random().nextInt(myhashSet.size());
    for(Object obj : myhashSet) {
        if (random-- == 0) {
            return obj;
        }
    }

Несмотря на то, что покончено с двумя вышеупомянутыми переменными, вышеупомянутое решение все еще остается случайным, потому что мы полагаемся на случайное (начиная со случайно выбранного индекса) уменьшение в сторону 0 на каждой итерации.

0 голосов
/ 02 марта 2011

после прочтения этой темы, лучшее, что я мог написать:

static Random random = new Random(System.currentTimeMillis());
public static <T> T randomChoice(T[] choices)
{
    int index = random.nextInt(choices.length);
    return choices[index];
}
0 голосов
/ 08 августа 2017

Если вы не возражаете против сторонней библиотеки, библиотека Utils имеет IterableUtils , который имеет метод randomFrom (Iterable iterable), который примет Set и вернет случайное элемент из него

Set<Object> set = new HashSet<>();
set.add(...);
...
Object random = IterableUtils.randomFrom(set);

Он находится в Центральном репозитории Maven по адресу:

<dependency>
  <groupId>com.github.rkumsher</groupId>
  <artifactId>utils</artifactId>
  <version>1.3</version>
</dependency>
0 голосов
/ 28 апреля 2016

С Гуавой мы можем сделать немного лучше, чем ответ Кот:

public static E random(Set<E> set) {
  int index = random.nextInt(set.size();
  if (set instanceof ImmutableSet) {
    // ImmutableSet.asList() is O(1), as is .get() on the returned list
    return set.asList().get(index);
  }
  return Iterables.get(set, index);
}
0 голосов
/ 04 января 2016

Если установленный размер не большой, то с помощью массивов это можно сделать.

int random;
HashSet someSet;
<Type>[] randData;
random = new Random(System.currentTimeMillis).nextInt(someSet.size());
randData = someSet.toArray();
<Type> sResult = randData[random];
0 голосов
/ 27 марта 2015

Общее решение, использующее ответ Хота в качестве отправной точки.

/**
 * @param set a Set in which to look for a random element
 * @param <T> generic type of the Set elements
 * @return a random element in the Set or null if the set is empty
 */
public <T> T randomElement(Set<T> set) {
    int size = set.size();
    int item = random.nextInt(size);
    int i = 0;
    for (T obj : set) {
        if (i == item) {
            return obj;
        }
        i++;
    }
    return null;
}
0 голосов
/ 24 февраля 2015

Самый простой в Java 8:

outbound.stream().skip(n % outbound.size()).findFirst().get()

где n - случайное целое число. Конечно, он имеет меньшую производительность, чем у for(elem: Col)

0 голосов
/ 04 февраля 2015

Если вы действительно хотите выбрать «любой» объект из Set, без каких-либо гарантий случайности, проще всего взять первое, возвращенное итератором.

    Set<Integer> s = ...
    Iterator<Integer> it = s.iterator();
    if(it.hasNext()){
        Integer i = it.next();
        // i is a "random" object from set
    }
...