Find if two arrays are repeated in array and then select them

后端 未结 6 805
后悔当初
后悔当初 2020-12-03 18:51

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]];
<
相关标签:
6条回答
  • 2020-12-03 19:05

    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 result
      return r
    }, { result: []}).result)             // print the result property

    0 讨论(0)
  • 2020-12-03 19:13

    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.

    0 讨论(0)
  • 2020-12-03 19:14

    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)),
                new Map
             ))
            .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))
            )
            (new Map)
        );
            
    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)))
            (new Set)
        );
            
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    0 讨论(0)
  • 2020-12-03 19:15

    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) + 1
    
                  return 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) + 1
      
      return temp[key] == 3
    })
    
    console.log(res)

    0 讨论(0)
  • 2020-12-03 19:19

    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 array
    const equal = (arr1, arr2) => arr1.every((n, j) => n === arr2[j])
    
    let GROUP_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)

    0 讨论(0)
  • 2020-12-03 19:21

    ES6:

    const repeatMap = {}
    
    array.forEach(arr => {
      const key = JSON.stringify(arr)
      if (repeatMap[key]) {
        repeatMap[key]++
      } else {
        repeatMap[key] = 1
      }
    })
    
    const repeatedArrays = Object.keys(repeatMap)
      .filter(key => repeatMap[key] >= 3)
      .map(key => JSON.parse(key))
    
    0 讨论(0)
提交回复
热议问题