我有一个数组数组,需要根据数组的前2个项对其进行过滤,以使其具有唯一性。
[
["18", "-66"],
["26", "-80"],
["26", "-80"],
["26", "-80"],
["27", "-80"],
["27", "-80"],
["28", "-97"],
["29", "-99"],
["30", "-81"],
["30", "-87"],
["30", "-99"],
["31", "-110"],
["31", "-110"],
["31", "-111"],
["31", "-84"],
["31", "-87"],
["31", "-95"],
["31", "-95"],
["31", "-95"]
]
虽然像这样的函数仅用一个唯一的函数就可以很好地完成工作,但我看不到如何修改它以搜索前两个项目:
function filterArray(incomingArray){
var unique = {};
var distinct = [];
for( var i in incomingArray ){
if( typeof(unique[incomingArray[i][0]]) == "undefined"){
distinct.push([incomingArray[i][0],{}]);
}
unique[incomingArray[i][0]] = 0;
}
return distinct;
}
整个数组不需要唯一,只需前两个项目,因此例如以下内容将匹配:
[
["26", "-80", 2],
["26", "-80", 3]
]
##更新##
我尝试了每种建议的方法,发现了一些有趣的东西。首先,我要感谢您提出解决问题的每一种想法/方式。在性能测试中,我提供了4000条记录,并对每种方法进行了性能测试。
Mark使用Set()在19ms内完成4000条记录的方法,而仅提供约50条记录则在2ms内完成。
D。 Seah的方法在149毫秒内完成了4000条记录,但在1ms内仅提供了50条记录。
vol7ron的4000条记录的方法在30毫秒内完成,但奇怪的是在52毫秒内完成了50条记录
Ben的方法我仍在研究它的工作方式,到目前为止,它还没有返回我期望的结果,但是随着它返回3维数组,我很想知道其他应用程序中还有什么可能性,但是大约花了38秒,我最终得到了一大堆undefined
。可能是我做错了,但至少在这种情况下,它可能比我需要的功能要强,并且由于其他解决方案足够快,因此我可以将其推迟到下一次。
使用Set()似乎是寻求与性能相关的解决方案的最佳方法,在该解决方案中,数据集可能会不断增长,但在较小的数据集中,vol7tron会获胜。
答案 0 :(得分:1)
如果您可以找到一个不会出现在数据中的字符,则可以使用该字符将您的前两个元素连接到一个键中。例如18_-66
。然后,您可以保留Set
的已知值并使用它进行过滤。集合中的关键查找是恒定时间,因此它应该以n为单位线性运行。例如:
let arr = [["18", "-66"],["26", "-80"],["26", "-80"],["26", "-80"],["27", "-80"],["27", "-80"],["28", "-97"],["29", "-99"],["30", "-81"],["30", "-87"],["30", "-99"],["31", "-110"],["31", "-110"],["31", "-111"],["31", "-84"],["31", "-87"],["31", "-95"],["31", "-95"],["31", "-95"]]
let s = new Set()
let f = arr.filter(item => {
let key = item[0] + '_' +item[1] // join elements 1 and 2 with _
return !s.has(key) && s.add(key) // add to set and return true if it's not already there
})
console.log(f)
答案 1 :(得分:1)
以下函数将遍历数组两次,如果前两项匹配,它将把包含两项的数组推入输出数组。
function filterArray(arr) {
var matching = []
for (i in arr) {
for (j in arr) {
if (arr[i][0] === arr[j][0] && arr[i][1] === arr[j][1]) {
matching.push([arr[i], arr[j]])
}
}
}
for (k in matching) {
matching[k] = [matching[k][0][0], matching[k][0][1], matching[k].count]
}
return matching
}
答案 2 :(得分:1)
最简单的管理方法是保留先前处理过的列表的缓存变量。如果在评估数组时它已经在缓存列表中,请不要存储它。如果它不在缓存中,则将其保留并在缓存中进行输入。
VK_KHR_xlib_surface
let cache = {};
let data = getData();
let unique = data.reduce((acc,curr)=>{
let key = [curr[0],curr[1]].join(',')
if (!cache[key]){
cache[key] = true;
acc.push(curr)
}
return acc;
},[])
console.log('unique: ', prettyPrint(unique))
console.log('cache: ', prettyPrint(cache))
function getData(){ return [
["18", "-66"],
["26", "-80"],
["26", "-80"],
["26", "-80"],
["27", "-80"],
["27", "-80"],
["28", "-97"],
["29", "-99"],
["30", "-81"],
["30", "-87"],
["30", "-99"],
["31", "-110"],
["31", "-110"],
["31", "-111"],
["31", "-84"],
["31", "-87"],
["31", "-95"],
["31", "-95"],
["31", "-95"]
]}
function prettyPrint(data){
if(Array.isArray(data)){
return '\n' + JSON.stringify(data,null,2)
.replace(/,\n\s+[^[\s]/g, ',')
.replace(/(\[)\s+([^[\s])/g, '$1$2')
.replace(/"\s+/g,'"')
}
else if (typeof data === 'object')
return '\n' + JSON.stringify(data,null,2)
else
return data;
}
是魔术的一部分。它通过定界符将两个值连接在一起,因此仅执行一次查找。在let key = [curr[0],curr[1]].join(',')
输出中更容易看到此值答案 3 :(得分:0)
您可以使用reduce函数
var oDistinct = oData.reduce(function (acc, cur) {
if (!acc.some(function(i) {
return i[0] === cur[0] && i[1] === cur[1];
})) {
acc.push(cur);
}
return acc;
}, []);