Skip to content Skip to sidebar Skip to footer

Find If Two Arrays Are Repeated In Array And Then Select Them

I have multiple arrays in a main/parent array like this: var array = [[1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]]; here are the array's for simpler readi

Solution 1:

Try this

array.filter(( r={}, a=>!(2-(r[a]=++r[a]|0)) ))

var array = [[1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]];

var r= array.filter(( r={}, a=>!(2-(r[a]=++r[a]|0)) ))

console.log(JSON.stringify(r));

Time complexity O(n) (one array pass by filter function). Inspired by Nitish answer.

Explanation

The (r={}, a=>...) will return last expression after comma (which is a=>...) (e.g. (5,6)==6). In r={} we set once temporary object where we will store unique keys. In filter function a=>... in a we have current array element . In r[a] JS implicity cast a to string (e.g 1,17). Then in !(2-(r[a]=++r[a]|0)) we increase counter of occurrence element a and return true (as filter function value) if element a occurred 3 times. If r[a] is undefined the ++r[a] returns NaN, and further NaN|0=0 (also number|0=number). The r[a]= initialise first counter value, if we omit it the ++ will only set NaN to r[a] which is non-incrementable (so we need to put zero at init). If we remove 2- as result we get input array without duplicates - or alternatively we can also get this by a=>!(r[a]=a in r). If we change 2- to 1- we get array with duplicates only.

UPDATE

Even shorter version based on @kencomment can be written (it should always work with arrays of numbers). The original longer version of @ken code is in snippet and shows how @ken uses in clever way second argument of .filter to avoid usage global variable r.

array.filter(a=>!(2-(this[a]=++this[a]|0)))

var array = [[1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]];

var r= array.filter(a=>!(2-(this[a]=++this[a]|0)), {})

console.log(JSON.stringify(r));

Solution 2:

You could take a Map with stringified arrays and count, then filter by count and restore the arrays.

var array = [[1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]],
    result = Array
        .from(array.reduce(
            (map, array) =>
                (json => map.set(json, (map.get(json) || 0) + 1))
                (JSON.stringify(array)),
            newMap
         ))
        .filter(([, count]) => count > 2)
        .map(([json]) =>JSON.parse(json));
        
console.log(result);
.as-console-wrapper { max-height: 100%!important; top: 0; }

Filter with a map at wanted count.

var array = [[1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]],
    result = array.filter(
        (map =>a => 
            (json =>
                (count => map.set(json, count) && !(2 - count))
                (1 + map.get(json) || 1)
            )
            (JSON.stringify(a))
        )
        (newMap)
    );
        
console.log(result);
.as-console-wrapper { max-height: 100%!important; top: 0; }

Unique!

var array = [[1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]],
    result = array.filter(
        (s =>a => (j => !s.has(j) && s.add(j))(JSON.stringify(a)))
        (newSet)
    );
        
console.log(result);
.as-console-wrapper { max-height: 100%!important; top: 0; }

Solution 3:

You can use Object.reduce, Object.entries for this like below

var array = [[1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]];


let res = Object.entries(
            array.reduce((o, d) => {
              let key = d.join('-')
              o[key] = (o[key] || 0) + 1return o
          }, {}))
          .flatMap(([k, v]) => v > 2 ? [k.split('-').map(Number)] : [])
  
  
console.log(res)

OR may be just with Array.filters

var array = [[1, 17], [1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]];

let temp = {}
let res = array.filter(d => {
  let key = d.join('-')
  temp[key] = (temp[key] || 0) + 1return temp[key] == 3
})

console.log(res)

Solution 4:

For a different take, you can first sort your list, then loop through once and pull out the elements that meet your requirement. This will probably be faster than stringifying keys from the array even with the sort:

var arr = [[1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]]
arr.sort((a, b) => a[0] - b[0] || a[1] - b[1])

// define equal for arrayconstequal = (arr1, arr2) => arr1.every((n, j) => n === arr2[j])

letGROUP_SIZE = 3
first = 0, last = 1, res = []

while(last < arr.length){
    if (equal(arr[first], arr[last])) last++
    else {
        if (last - first >= GROUP_SIZE)  res.push(arr[first])
        first = last
    }
}
if (last - first >= GROUP_SIZE)  res.push(arr[first])
console.log(res)

Solution 5:

You could also do this with a single Array.reduce where you would only push to a result property if the length is equal to 3:

var array = [[1, 17], [1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]];

console.log(array.reduce((r,c) => {
  let key = c.join('-')
  r[key] = (r[key] || 0) + 1
  r[key] == 3 ? r.result.push(c) : 0// if we have a hit push to resultreturn r
}, { result: []}).result)             // print the result property

Post a Comment for "Find If Two Arrays Are Repeated In Array And Then Select Them"