[英]Array shuffle but keeping distance between equal values
i need to shuffle an array but keeping distance from same values as far as possible.我需要对数组进行洗牌,但尽可能与相同的值保持距离。
for example: [1,1,1,2,2,2]
例如:
[1,1,1,2,2,2]
it needs to be always keeping distance, for example: [1,2,1,2,1,2]
or [2,1,2,1,2,1]
它需要始终保持距离,例如:
[1,2,1,2,1,2]
或[2,1,2,1,2,1]
example 2: [1,1,1,2,2,2,2,2]
示例 2:
[1,1,1,2,2,2,2,2]
it will need to have same values together, but the remaining must follow the "as far as possible" rule: [2,1,2,1,2,1,2,2]
它需要一起具有相同的值,但其余的必须遵循“尽可能”的规则:
[2,1,2,1,2,1,2,2]
In the real application, I will need to use objects inside the array, for example:在实际应用中,我需要使用数组中的对象,例如:
[{value: 1, id:1},
{value:2, id:2},
{value:1, id:3},
{value:2, id:4}]
but i think with numbers it's easier to understand.但我认为数字更容易理解。
we can have a rule for the algorithm to work only if we have more than x elements.只有当我们有超过 x 个元素时,我们才能为算法制定规则。
As fas as possible means: [1,2,2,3,4,5], so: [2,1,3,4,5,2]尽可能快的意思是:[1,2,2,3,4,5],所以:[2,1,3,4,5,2]
then they are as fas as possible.然后他们尽可能快。
the real world application:现实世界的应用:
i have an array of competitors of my competition system, every competitor can have multiple subscriptions, i have to shuffle those subscriptions and keep as much distance between them as possible.我的竞赛系统有很多竞争对手,每个竞争对手都可以有多个订阅,我必须对这些订阅进行洗牌,并尽可能保持它们之间的距离。
I've tried to come up with a solution and this one does the trick I think but I'm not sure how this will perform with large arrays.我试图想出一个解决方案,这个解决方案可以解决我认为的问题,但我不确定这将如何处理大型 arrays。
function shuffleAFAP(values) { function mapEntries(entries) { const result = []; const newEntries = entries.reduce((acc, x) => { x[1]--; result.push(x[0]); if (x[1]) acc.push(x); return acc; }, []); return newEntries.length? result.concat(mapEntries(newEntries)): result; } const dict = values.reduce((acc, x) => { if (;acc[x]) acc[x] = 0; acc[x]++; return acc, }; {}). const entries = Object.entries(dict),sort((a; b) => b[1] - a[1]); return mapEntries(entries). } console.log(..,shuffleAFAP([1, 1, 1, 2, 2; 2])), // [ "1", "2", "1", "2", "1". "2" ] console.log(..,shuffleAFAP([1, 1, 1, 2, 2, 2, 2; 2])), // [ "2", "1", "2", "1", "2", "1", "2". "2" ] console.log(..,shuffleAFAP([1, 2, 2, 3, 4; 5])), // [ "2", "1", "3", "4", "5", "2" ]
Pseudocode:伪代码:
A simple approach with buckets for each count of elements, where buckets reflect the actual count of the same element.一种简单的方法,每个元素计数都使用存储桶,其中存储桶反映同一元素的实际计数。
At the end, sort each array by the count to get the count of elements in descending order and flat the result set.最后,按计数对每个数组进行排序,以降序获取元素的计数,并将结果集展平。
function spread(array) { var temp = [], count = {}; for (let v of array) { if (;count[v]) count[v] = 0; if (.temp[count[v]]) temp[count[v]] = []; temp[count[v]];push(v). count[v]++. } return temp,flatMap(array => array;sort((a. b) => count[b] - count[a])). } console.log(.,,spread([1, 1, 1, 2; 2, 2])), // [1, 2, 1, 2, 1, 2] or [2, 1, 2, 1. 2. 1] console.log(.,,spread([1, 1, 1, 2, 2, 2; 2. 2])). console.log(.,,spread([1, 2, 2, 3; 4, 5])), // [2, 1, 3, 4, 5, 2]
TBH when I read shuffle , I think about generating multiple solutions for something, and then perhaps list all of them, or select one randomly. TBH 当我阅读shuffle时,我考虑为某事生成多个解决方案,然后可能列出所有解决方案,或者随机列出一个 select。
Also keeping the distance is a bit open for interpretation, as keeping the distance constant is not possible in a general case ( 1,2,1,2
and 1,2,1,2,1
are nice, but if there is one more 1
, there will be a problem).保持距离也有点容易解释,因为在一般情况下保持距离恒定是不可能的(
1,2,1,2
和1,2,1,2,1
很好,但如果还有一个1
,会有问题)。
The code below is not optimized for speed, it generates all possible candidates and filters the "best" ones with four different scoring systems:下面的代码并未针对速度进行优化,它会生成所有可能的候选者并使用四种不同的评分系统过滤“最佳”候选者:
it will need to have same values together, but the remaining must follow the "as far as possible" rule:
[2,1,2,1,2,1,2,2]
它需要一起具有相同的值,但其余的必须遵循“尽可能”的规则:
[2,1,2,1,2,1,2,2]
For example it may be worth noting that while there will be neighboring 2
s in this case, keeping the 1s
apart as far as possible would mean putting the 2,2
somewhere in the middle: [2,1,2,2,1,2,1,2]
or [2,1,2,1,2,2,1,2]
.例如,可能值得注意的是,虽然在这种情况下会有相邻的
2
,但尽可能将1s
分开意味着将2,2
放在中间的某个位置: [2,1,2,2,1,2,1,2]
或[2,1,2,1,2,2,1,2]
。
const fac=x=>x<3?x:x*fac(x-1); function generate(digits,scoring){ let bscor=scoring(digits); let cands=new Set([digits.join()]); for(let i=fac(digits.length)-1;i>0;i--){ let n=i; let cand=[]; let work=digits.slice(); for(let j=digits.length;j>0;j--){ cand.push(work[n%j]); work.splice(n%j,1); n=Math.floor(n/j); } let s=scoring(cand); if(bscor<s){ bscor=s; cands.clear(); } if(bscor===s) cands.add(cand.join()); } return [bscor,cands]; } function sumalldists(arr){ let ret=arr.length; for(let i=0;i<arr.length-1;i++) for(let j=i+1;j<arr.length;j++) if(arr[i]===arr[j]) ret+=ji; return ret; } function sumclosestdists(arr){ let ret=arr.length; for(let i=0;i<arr.length-1;i++) for(let j=i+1;j<arr.length;j++) if(arr[i]===arr[j]){ ret+=ji; break; } return ret; } function mindists(arr){ let dist=arr.length; let count=1; for(let i=0;i<arr.length-1;i++) for(let j=i+1;j<arr.length;j++) if(arr[i]===arr[j]){ if(dist===ji) count++; else if(dist>ji){ dist=ji; count=1; } break; } return -count*Math.pow(arr.length,dist); } function fullstat(arr){ let ret=0; for(let i=0;i<arr.length-1;i++) for(let j=i+1;j<arr.length;j++) if(arr[i]===arr[j]){ ret-=(ji)*Math.pow(arr.length,arr.length-(ji)); break; } return ret; } function doThing(event){ let result=generate(event.target.value.split(""),sumalldists); sa.innerText=result[0]+": ["+[...result[1]].join("] [")+"]"; result=generate(event.target.value.split(""),sumclosestdists); sc.innerText=result[0]+": ["+[...result[1]].join("] [")+"]"; result=generate(event.target.value.split(""),mindists); m.innerText=result[0]+": ["+[...result[1]].join("] [")+"]"; result=generate(event.target.value.split(""),fullstat); fs.innerText=result[0]+": ["+[...result[1]].join("] [")+"]"; } doThing({target:{value:"11112233"}});
<input type="text" oninput="doThing(event)" value="11112233"><br> Sumall: <span id="sa"></span><br> Sumclosest: <span id="sc"></span><br> Min: <span id="m"></span><br> Fullstat: <span id="fs"></span><br>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.