var arr = [
{type: 'first', name: 'A'},
{type: 'other', name: 'other_Z'},
{type: 'first', name: 'B'},
{type: 'other', name: 'other_x'},
{type: 'first', name: 'C'},
{type: 'other', name: 'other_y'}
]
var arr = [
{type: 'first', name: 'A'},
{type: 'other', name: 'other_Z'},
{type: 'first', name: 'B'},
{type: 'other', name: 'other_x'},
{type: 'first', name: 'C'},
{type: 'other', name: 'other_y'}
]
返回第一条数据的 type: 'first'
为必须条件
不太懂什么意思 按照我的理解写了
当 type: first
数据占比不算低的时候可以这么写
const getRandomItem = (arr, num) => {
const items = []
const indexes = {}
while (num --) {
let i
do {
i = (Math.random() * 1e6 | 0) % arr.length
}
while (indexes[i] || (! items.length && arr[i].type !== 'first'))
indexes[i] = true
items.push(arr[i])
}
return items
}
当 type: first
较少时可以这么写提高效率
const getRandomItem = (arr, num, indexes = {}) => {
const items = []
while (num --) {
let i
do {
i = (Math.random() * 1e6 | 0) % arr.length
}
while (indexes[i])
indexes[i] = true
items.push(arr[i])
}
return items
}
const getRandomItemWithFirst = (arr, num) => {
const first = []
for (const item of arr) {
if (item.type === 'first') first.push(item)
}
const i_first = (Math.random() * 1e6 | 0) % first.length
const indexes = { [i_first]: true }
return [ arr[i_first] ].concat(getRandomItem(arr, num - 1, indexes))
}
当数据很小你只想链式一把梭的时候可以这么写
const getRandomItem = (arr, num) => Array(num)
.fill()
.map((_, i, self) => {
while (true) {
const v = arr[(Math.random() * 1e6 | 0) % arr.length]
if ((v.type === 'first' || i) && ! self.includes(v)) return v
}
})
@边城 @ForkKILLET 我偷个懒咋儿样?
const total = 3; // 随机选出几条
// arr 是目标,具有6条记录
const rows = []; // 随机选出的记录
for(let i = 0, l = arr.length; i < l; i ++) {
// 已经选够了
if (rows.length === total) break;
// 如果随机到的数据数量低于目标数量,且与未遍历的记录数量一致,那么肯定入选
if (arr.length - i - 1 === total - rows.length) {
rows.push(arr[i]);
} else if (Math.random() >= 0.5) {
rows.push(arr[i]);
}
};
至于第一条必选,将上面代码改成total是2, rows = [arr[0]],然后for循环从1开始就行了。
已参与了 SegmentFault 思否社区 10 周年「问答」打卡 ,欢迎正在阅读的你也加入。
27 回答13k 阅读
8 回答3.5k 阅读✓ 已解决
6 回答1.3k 阅读✓ 已解决
5 回答5.3k 阅读✓ 已解决
4 回答1.6k 阅读✓ 已解决
3 回答1.7k 阅读
4 回答2.3k 阅读✓ 已解决
用 Lodash 写起来比较简单,不过这段程序还有一些优化空间:
不用完全洗牌,采用抽取,分离,再从剩余数据中抽取 …… 的方式来做(就是把洗牌算法用来抽取)
这个可以参考:
补充,如果按另一种理解 ——
如果是随机选择任意项,仅要求第 1 项符合
type === "first"
的要求。那么不用分组,只需要先把 first 过滤出来,随机选 1 个,跟序号为 0 的元素交换位置;后面仍然按洗牌算法随机挨个选择,挨个往前放就好。简单地说就是:仍然是使用洗牌算法来选择,只不过第 1 个选择比较特殊,单独处理