Find If Two Arrays Are Repeated In Array And Then Select Them
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"