一个数组通过配置随机抽取组成小数组
发布于: 2021 年 03 月 31 日
1.场景
现有一个数组,想抽出其中一部分元素组成另外一个小一点的数组,又不希望完全随机抽出,比如希望原数组的前 20%抽多点,中间的 50%少抽点,最后的 30%再多抽点,而且希望在范围内是不重复随机抽取
2.思路将不同的配置,转化成固定要取的数量的区域,再从不同的区域里使用不重复随机算法取
3.Java Code
package kowalski;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
/**
* Created by kowalski.zhang on 2018/6/6
*/
public final class PickUtil {
private static Random random = ThreadLocalRandom.current();
private PickUtil() {
}
/***
* just pick with config
* @param srcList
* @param configs
* @param <T>
* @return
*/
public static <T> List<T> levelPickWithNewByConfig(List<T> srcList, Double[]... configs) {
if (srcList == null || srcList.isEmpty()) {
return Collections.emptyList();
}
List<T> res = new ArrayList<>(srcList.size());
int lastIndex = 0;
for (Double[] config : configs) {
int modelLen = config[0].intValue();
/**获取长度大于等于有效长度 全额取出*/
if (modelLen <= config[1]) {
for (int m = 0; m < modelLen; m++) {
res.add(srcList.get(lastIndex + m));
}
} else {
/**区域内使用不重复随机算法pick*/
int randLen = config[1].intValue();
int tempModelLen = modelLen;
for (int m = 0; m < randLen; m++) {
int randNum = random.nextInt(tempModelLen);
res.add(srcList.get(randNum + lastIndex));
tempModelLen--;
}
}
lastIndex += modelLen;
}
return res;
}
/**
* pick
* @param srcList
* @param configs 取出配置
* @param pickNum 最大取出量
* @param <T>
* @return
*/
public static <T> List<T> levelPickWithNew(List<T> srcList, Double[][] configs, ConfigTypeEnum typeEnum, Integer pickNum) {
if (pickNum < srcList.size()) {
return srcList;
}
switch (typeEnum){
case FIXED_FIXED:
return levelPickWithNewByConfig(srcList, configs);
case JUST_PERCENT:
return levelPickWithNewByConfig(srcList, exchangeConfigToFixNum(srcList.size(), configs));
case PERCENT_FIXED:
return levelPickWithNewByConfig(srcList, exchangeConfigToFixNum(srcList.size(), pickNum, configs));
}
return srcList;
}
public static <T> List<T> levelPickWithNew(List<T> srcList, Double[][] configs, ConfigTypeEnum typeEnum) {
return levelPickWithNew(srcList, configs, typeEnum, null);
}
/**
* 将ConfigTypeEnum.PERCENT_FIXED转化成对应的FIXED_FIXED配置
* @param listLen
* @param configs
* @return
*/
public static Double[][] exchangeConfigToFixNum(int listLen, Double[]... configs) {
Double[][] res = new Double[configs.length][configs[0].length];
int total = 0;
for (int i = 0; i < configs.length - 1; i++) {
int temp = (int) (configs[i][0] * listLen);
total += temp;
res[i][0] = (double) temp;
}
/**最后一个配置收拾残局*/
if (listLen > total) {
res[configs.length - 1][0] = (double) (listLen - total);
}
return res;
}
/***
* ConfigTypeEnum.JUST_PERCENT转化成对应的FIXED_FIXED配置
* @param listLen
* @param pickNum
* @param configs
*/
public static Double[][] exchangeConfigToFixNum(int listLen, Integer pickNum, Double[]... configs) {
if (pickNum == null || pickNum < 0) {
throw new RuntimeException("pickNum not leagal !!!");
}
Double[][] res = new Double[configs.length][configs[0].length];
int total = 0;
int totalPick = 0;
for (int i = 0; i < configs.length - 1; i++) {
int temp = (int) (configs[i][0] * listLen);
int tempPick = (int) (configs[i][0] * pickNum);
total += temp;
totalPick += tempPick;
res[i][0] = (double) temp;
res[i][1] = (double) tempPick;
}
/**最后一个配置收拾残局*/
if (listLen > total) {
res[configs.length - 1][0] = (double) (listLen - total);
}
if (pickNum > totalPick) {
res[configs.length - 1][1] = (double) (pickNum - totalPick);
}
return res;
}
public enum ConfigTypeEnum {
PERCENT_FIXED(1, "百分比-固定量"),
FIXED_FIXED(2, "固定量-固定量"),
JUST_PERCENT(4, "仅百分比"),;//必须传期待List大小(pickNum)
private Integer type;
private String desc;
ConfigTypeEnum(Integer type, String desc) {
this.type = type;
this.desc = desc;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public String getDesc() {
return desc;
}
private static final Map<Integer, ConfigTypeEnum> map = new HashMap<>();
static {
for (ConfigTypeEnum enums : ConfigTypeEnum.values()) {
map.put(enums.getType(), enums);
}
}
public static ConfigTypeEnum getEnumValue(int code) {
return map.get(code);
}
public static String getDescByType(int code) {
return map.get(code).getDesc();
}
public void setDesc(String desc) {
this.desc = desc;
}
}
public static void main(String... args) {
Double[][] configs = { { 0.15d, 10.0d }, { 0.25d, 15.0d }, { 0.6d, 30.0d } };
ConfigTypeEnum configType = ConfigTypeEnum.PERCENT_FIXED;
}
}
复制代码
有更好方式的小伙伴欢迎交流~~e:995517265@qq.com
划线
评论
复制
发布于: 2021 年 03 月 31 日阅读数: 9
版权声明: 本文为 InfoQ 作者【迟到的月亮】的原创文章。
原文链接:【http://xie.infoq.cn/article/fff44fcf2a0d12929706d8560】。文章转载请联系作者。
迟到的月亮
关注
还未添加个人签名 2020.03.30 加入
还未添加个人简介
评论