【Web前端问题】JS循环嵌套问题?

现有一个函数change,接收两个参数,参数arr为一数组,形如 ["A","T","C","G"] ,该数组元素值只可能为字符串"A","T","C","G"之一,参数count为一int,值小于等于arr的长度。
函数change实现的功能是将数组arr内的count个元素改为除原值以外的ATCG中另外三个,如"A"改为 "T"/"C"/"G" ,然后输出一个新的二维数组outPut,outPut内每个元素都是一个数组,其值为改变后的所有可能性。


如:原数组arr=["A","C"],改变个数count=1
输出数组

outPut=[

["T","C"],["C","C"],["G","C"],["A","A"],["A","T"],["A","G"]

]


写了如下函数change,写到一半发现循环嵌套层数问题,不知如何继续,求助~~~

function change(arr,count){

for(var i = 0; i < arr.length; i ++){

switch (arr[i]){

case "A":

}

}

}

回答:

以下是一种递归实现:

const legalVals = ['A', 'C', 'G', 'T'];

function change(arr, count) {

count = parseInt(count);

if (!Array.isArray(arr) || count < 0 || count > arr.length) throw `Illegal argument`;

if (arr.find(e => !legalVals.includes(e))) throw `Illegal member(s)`;

if (arr.length === 0 || count === 0) return [arr];

return doChange(arr, count)

}

function doChange(arr, count) {

const length = arr.length;

//数组的第一个元素

const v0 = arr[0];

//第一个元素可以替换的值

const diff0 = legalVals.filter(e => e !== v0);

//边界条件:不替换任何值

if (count === 0) {

return [arr];

}

//边界条件:长度为1且只替换1个

if (length === 1) {

return diff0.map(e => [e]);

}

//替换掉第一个元素的结果

const change1st = unshiftEach(diff0, doChange(arr.slice(1), count - 1));

//边界条件:如果count === length,那么第一个元素是必须替换的

if (count === length) {

return change1st;

}

//不替换第一个的结果

const changeOthers = unshiftEach([v0], doChange(arr.slice(1), count));

//排除以上边界条件的通常情况,总结果= 替换掉第一个元素的结果 + 不替换第一个的结果

return change1st.concat(changeOthers);

}

//将arr的每个元素拼接到arr2(二维数组)的每个元素前。(笛卡尔积)

function unshiftEach(arr, arr2) {

return arr2.flatMap(item =>

arr.map(e => {

const result = item.slice();

result.unshift(e);

return result;

})

)

}

回答:

提供一个我认为比较好理解的思路,分为两个步骤来处理
图片描述

代码实现

const allKey = ['A', 'T', 'C', 'G']

const isArray = Array.isArray

// 聚合多个数组

// [[A,B],[C,D]] => [[A,C],[A,D],[B,C],[B,D]]

function pair(arr1, arr2, ...arrs) {

if (!arr2) return arr1

if (!arrs[0]) {

return arr1.reduce(

(acc, a1) =>

acc.concat(arr2.map(a2 => (isArray(a1) ? a1 : [a1]).concat(a2))),

[],

)

}

return pair(pair(arr1, arr2), ...arrs)

}

function change(arr, count) {

let group1 = []

// 根据 count 从 arr 中确定需要改变部分和不变部分的组合

for (let i = 0; i < arr.length - count + 1; i++) {

let item = [...arr]

item.splice(i, count, arr.slice(i, i + count))

group1.push(item)

}

let group2 = []

// 替换需要改变部分

for (let i = 0; i < group1.length; i++) {

const item = group1[i]

for (let j = 0; j < item.length; j++) {

const item1 = item[j]

if (isArray(item1)) {

const before = item.slice(0, i)

const dif = item1.map(e => allKey.filter(v => v !== e))

const after = item.slice(i + 1, item.length)

group2 = group2.concat(pair(...[[before], ...dif, [after]]))

}

}

}

return group2

}

图片描述

回答:

从arr中挑选出来需要保存的(arr.length - count)所有可能的组合,然后再从原数组中挑选出来所有可能的(count)补充组合,然后拼在一起去重就行了。

(async ()=>{

let vari = ['A','T','C','G'];

function change(arr, count = 1){

arr = arr.map(a=>vari.indexOf(a)).sort(); // convert to int array, for easier sorting in future

var prefix = combination(arr, arr.length - count);

var suffix = combination([0,1,2,3], count);

var res = prefix.length === 0 ? suffix : prefix.map(p=>suffix.map(s=>[...p, ...s])).reduce((a,b)=>[...a,...b], []);

var existing = arr.join(",");

res = res

.filter(r=>new Set(r).size === r.length) // filter out ones with duplicated items, like ["A","A","C"]

.map(r=>r.sort()) // order items, so ["C","A"] becomes ["A", "c"]

.sort() // sort, just make it looks prettier

.reduce((a,b)=>{ // remove duplicated combinations, keep only one

if(a[b.join(",")] === void 0){

a.arr.push(b);

a[b.join(",")] = 0;

}

return a;

}, {arr: []}).arr

.filter(r=>r.join(",") !== existing);

return res.map(r=>r.map((i)=>vari[i]));// convert back to letters

}

function combination(src, pick){

if(pick > src.length){

return [];

}

if(pick === 1){

return src.map(s=>[s]);

}

var res = [];

for(var i=0;i<src.length;i++){

for(var r of combination(src.slice(i+1), pick - 1)){

res.push([src[i], ...r]);

}

}

return res;

}

console.log(change(["G","A","C"], 2));

})();

output [A,T,C],[A,T,G],[T,C,G]

回答:

没看太懂,如果count是2,结果是不是t,gg,g

回答:

  1. 没说数组成员是否允许重复
  2. i最后不是做++操作,而是加count,因为每次替换的是count个,就是循环粒度

  3. 每次从arr里取出count个元素,求它们与原始数组的差,也就是除了count个元素以外的元素,将它们循环填入取出元素的位置,然后push到result数组
  4. 循环结束后返回result数组
  5. 注意处理一些意外情况

回答:

是不是应该就是,指定数量搞一个枚举,然后除去原始数据那种排列,就是结果。

以上是 【Web前端问题】JS循环嵌套问题? 的全部内容, 来源链接: utcz.com/a/141990.html

回到顶部