简体   繁体   中英

How to .concat multiple array that has at least one same element?

I've been working on this algorithm couple of hour and no luck so far, keep getting into many confusing nested for loops and maximum stack

Here is the goal,

Given an input of 2D array :

[[1,7],[1,3],[9,7],[2,4]]

I want the output to be 2D array again but they group together the element (from input array) that has at least one element is equal to the other element, like connecting the dot.

So the output be like

[[1,7,1,3,9,7],[2,4]]

Why? Because..

  • we can connect [1,7] with [1,3] they have 1 in common,
  • we can connect [1,7] with [9,7] they have 7 in common,
  • we can not connect [2,4] to anything since we don't have any common 2 or 4 values

So, for example

var input = [[1,7],[1,3],[9,7],[2,4]];
var output = (function(input) {
   // something i couldn't figure out
   // return = [[1,7,1,3,9,7],[2,4]]
})(input);
// as simple as that

You can use reduce method to create new array, and in each iteration check accumulator value to see if some sub-array contains some element from current array using findIndex and some methods.

 const data = [[1,7],[1,3],[9,7],[2,4]]; const data2 = [[50], [1,7],[1,3],[9,7],[11,12],[22, 13], [40, 100], [11, 40], [50, 13], [50, 13, 100]] const connect = (input, repeat = true) => { return input.reduce(function(r, e, i, arr) { if (!r.length) r.push(e); else { let index = r.findIndex(a => a.some(el => e.includes(el))); index != -1 ? r[index].push(...e) : r.push(e) } if (repeat) r = connect(r, false) return r; }, []) } let result = connect(data) console.log(JSON.stringify(result)) let result2 = connect(data2) console.log(JSON.stringify(result2)) 

Generally, when you encounter many nested for loops and maximum stack errors, it's because your problem would be best solved recursively. It's possible to do this without recursion, but much easier with it.

const input=[[1,7],[1,3],[9,7],[2,4]]
const output=(_input)=>{
    const first=_input[0]
    const match=_input.slice(1).findIndex(_sub=>_sub.some(_element=>first.includes(_element)))
    if(match==-1){
        if(_input.length<=2){
            return _input
        }
        return [first,...output(_input.slice(1))]
    }
    const joined=[first.concat(_input[match+1]),..._input.slice(1,match+1),..._input.slice(match+2)]
    return output(joined)
}

console.log(output(input)) //[[1,7,1,3,9,7],[2,4]]

I also tested this with xcodes' list in his comment to Nenad.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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