基于2个值将数组数组过滤为唯一?

时间:2018-07-20 23:47:47

标签: javascript jquery arrays

我有一个数组数组,需要根据数组的前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会获胜。

4 个答案:

答案 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;
}, []);