我在主/父数组中有多个数组,如下所示:
var array = [[1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]];
以下是用于简化阅读的数组:
[1, 17]
[1, 17]
[1, 17]
[2, 12]
[5, 9]
[2, 12]
[6, 2]
[2, 12]
[2, 12]
我想选择重复3次或更多次(> 3)的数组并将其分配给变量。因此,在此示例中,var repeatedArrays
将是[1, 17]
和[2, 12]
。
所以这应该是最终结果:
console.log(repeatedArrays);
>>> [[1, 17], [2, 12]]
我发现了类似的here,但它使用了underscore.js和lodash。
如何使用javascript甚至jquery(如果需要)呢?
答案 0 :(得分:9)
您可以使用Map
带有字符串化数组和计数,然后按计数过滤并恢复数组。
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; }
使用所需数量的地图进行过滤。
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; }
唯一!
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; }
答案 1 :(得分:7)
尝试一下
array.filter(( r={}, a=>!(2-(r[a]=++r[a]|0)) ))
时间复杂度 O(n)(一个数组通过过滤器函数传递)。受Nitish答案的启发。
说明
(r={}, a=>...)
将返回逗号后的最后一个表达式(即a=>...
)(例如(5,6)==6
)。在r={}
中,我们只设置了一个临时对象,用于存储唯一键。在a=>...
中的过滤器功能a
中,我们有当前的array
元素。在r[a]
中,JS将a
隐式转换为字符串(例如1,17
)。然后在!(2-(r[a]=++r[a]|0))
中,我们增加出现元素a
的计数器,如果元素a
出现3次,则返回true(作为过滤器功能值)。如果未定义r[a]
,则++r[a]
返回NaN
,然后返回NaN|0=0
(也返回number|0=number
)。 r[a]=
会初始化第一个计数器值,如果我们省略它,++
只会将NaN
设置为r[a]
,这是不可递增的(因此我们需要在初始化时置零) 。如果我们删除2-
作为结果,我们将获得没有重复的输入数组-或者,我们也可以通过a=>!(r[a]=a in r)
来获取它。如果将2-
更改为1-
,我们将得到仅包含重复项的数组.
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));
答案 2 :(得分:5)
您可以像下面这样使用Object.reduce
,Object.entries
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可能仅与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)
答案 3 :(得分:4)
换一种说法,您可以先对列表进行排序,然后循环浏览一次,然后取出满足您要求的元素。这可能比对数组中的键进行字符串化甚至更快,甚至可以进行排序:
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)
答案 4 :(得分:1)
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))
答案 5 :(得分:1)
您也可以使用单个Array.reduce
来执行此操作,其中只有当长度等于3时,才需要推送到result
属性:
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