如何从集合中随机选取一个元素? 我特别感兴趣的是从a中随机选取一个元素 Java中的HashSet或LinkedHashSet。 也欢迎其他语言的解决方案。


当前回答

为了好玩,我写了一个基于拒绝抽样的RandomHashSet。这有点粗糙,因为HashMap不让我们直接访问它的表,但它应该工作得很好。

它不使用任何额外的内存,查找时间是O(1)平摊。(因为java哈希表是密集的)。

class RandomHashSet<V> extends AbstractSet<V> {
    private Map<Object,V> map = new HashMap<>();
    public boolean add(V v) {
        return map.put(new WrapKey<V>(v),v) == null;
    }
    @Override
    public Iterator<V> iterator() {
        return new Iterator<V>() {
            RandKey key = new RandKey();
            @Override public boolean hasNext() {
                return true;
            }
            @Override public V next() {
                while (true) {
                    key.next();
                    V v = map.get(key);
                    if (v != null)
                        return v;
                }
            }
            @Override public void remove() {
                throw new NotImplementedException();
            }
        };
    }
    @Override
    public int size() {
        return map.size();
    }
    static class WrapKey<V> {
        private V v;
        WrapKey(V v) {
            this.v = v;
        }
        @Override public int hashCode() {
            return v.hashCode();
        }
        @Override public boolean equals(Object o) {
            if (o instanceof RandKey)
                return true;
            return v.equals(o);
        }
    }
    static class RandKey {
        private Random rand = new Random();
        int key = rand.nextInt();
        public void next() {
            key = rand.nextInt();
        }
        @Override public int hashCode() {
            return key;
        }
        @Override public boolean equals(Object o) {
            return true;
        }
    }
}

其他回答

在Java中:

Set<Integer> set = new LinkedHashSet<Integer>(3);
set.add(1);
set.add(2);
set.add(3);

Random rand = new Random(System.currentTimeMillis());
int[] setArray = (int[]) set.toArray();
for (int i = 0; i < 10; ++i) {
    System.out.println(setArray[rand.nextInt(set.size())]);
}

Icon有一个集合类型和一个随机元素操作符,一元“?”,因此表达式

? set( [1, 2, 3, 4, 5] )

将产生1到5之间的随机数。

当程序运行时,随机种子被初始化为0,因此要在每次运行时产生不同的结果,请使用randomize()

读完这篇文章后,我能写的最好的是:

static Random random = new Random(System.currentTimeMillis());
public static <T> T randomChoice(T[] choices)
{
    int index = random.nextInt(choices.length);
    return choices[index];
}

既然你说“其他语言的解决方案也欢迎”,下面是Python的版本:

>>> import random
>>> random.choice([1,2,3,4,5,6])
3
>>> random.choice([1,2,3,4,5,6])
4

数学:

a = {1, 2, 3, 4, 5}

a[[ ⌈ Length[a] Random[] ⌉ ]]

或者,在最近的版本中,简单地说:

RandomChoice[a]

Random[]生成一个0到1之间的伪随机浮点数。它乘以列表的长度,然后使用ceiling函数四舍五入到下一个整数。该索引然后从。

由于哈希表功能在Mathematica中经常使用规则,并且规则存储在列表中,因此可以使用:

a = {"Badger" -> 5, "Bird" -> 1, "Fox" -> 3, "Frog" -> 2, "Wolf" -> 4};