繁体   English   中英

如何从Arraylist Java中随机选择对

[英]How to pick pair randomly from Arraylist Java

示例我有这个对象的ArrayList:

clusterData: [{BitSet: [1, 1], Entropy: 0.0}, {BitSet: [1, 0], Entropy: 1.0}, {BitSet: [0, 0], Entropy: 0.0}, {BitSet: [0, 0], Entropy: 0.0}, {BitSet: [0, 0], Entropy: 0.0}]  

并且具有相似的BitSet和Entropy值的那些将成为可能的对,在这种情况下,它将产生:
配对#2与配对#3
配对#2与配对#4
配对#3与配对#4

那么,如何从产生的三个对中随机选择三个对中的一个并存储在另一个ArrayList中呢?

这是我的代码:

System.out.println("clusterData: " + clusterData);

    for (int i = 0; i < clusterData.size()-1; i++){
        for (int j = i+1; j < clusterData.size(); j++){
            if (clusterData.get(i).getBitSet().equals(clusterData.get(j).getBitSet()) && clusterData.get(i).getEntropy() == clusterData.get(j).getEntropy()){
                System.out.println("Pair #" + i + " WITH Pair #" + j);


            }
        }

    }    

请帮忙。

从整个集合中随机抽取第一个。 从较小的集合中选取下一个(代表您不希望两个数字相同的事实)。 如果第二个匹配或超过第一个,则添加一个。 然后分配给ij使i < j

// pick a from set [0..n)
// pick b from set [0..n-1)
//     which can also be represented as two sets
//           [0..a)[a..n-1)
// add one when b >= a, meaning b is in the sets:
//           [0..a)(a..n)

Random r;
int a = r.nextInt(clusterData.size());
int b = r.nextInt(clusterData.size()-1);
if (b >= a)
  b++;
if (a < b) {
  i = a;
  j = b;
} else {
  i = b;
  j = a;
}

您可以将所有可能的对添加到List然后随机选择其中一个元素。

该代码将在O(N²)中运行,其中N是输入数据的大小。


一种更有效的方法是将聚类数据分组到等价类(假设相似关系是等价关系,在这里似乎是这种情况[传递性对该方法很重要])。

在这里,我将使用ClusterData作为元素类型的类型名称。

如果群集数据相似,则重写equalsClusterData hashCode返回true /相同的哈希码。

然后创建一个Map<ClusterData, List<Integer>>将不同的ClusterData值映射到ClusterData列表中元素的clusterData列表。

Map<ClusterData, List<Integer>> equivalenceClasses = IntStream.range(0, clusterData.size()).boxed()
                                                              .collect(Collectors.groupingBy(clusterData::get)); 

在下一步中计算可能的对数:

public static int choose2(int elements) {
    return elements * (elements - 1) / 2;
}
int pairCount = equivalenceClasses.values().stream().mapToInt(lst -> choose2(lst.size())).sum();

确定其中一个等效类,其中每个等效类的概率与其可以提供的对的数量成正比:

if (pairCount == 0) {
    throw new IllegalArgumentException("No valid combinations");
}

Random random = ...

int choice = random.nextInt(pairCount);

List<Integer> classIndices = null;

for (List<Integer> indices : equivalenceClasses.values()) {
    choice -= choose2(indices.size());
    if (choice < 0) {
        classIndices = indices;
        break;
    }
}

最后,从等效类中选择一个组合:

int first = random.nextInt(classIndices.size());
int second = random.nextInt(classIndices.size()-1);
if (second >= first) {
    second++;
}
int firstIndex = classIndices.get(first);
int secondIndex = classIndices.get(second);

// TODO: swap indices, if firstIndex needs to be smaller than secondIndex
//       and it's not already the case

System.out.println("Chosen combination: Pair #" + firstIndex + " WITH Pair #" + secondIndex);

这应该在O(N)上运行,并提高大型输入数据的性能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM