如何在javascript中删除数组中的重复项

时间:2014-01-16 10:28:41

标签: javascript arrays

我为一个好的搜索提出了一个通用标题,但我的问题更具体一些。

我有一个阵列:

var keywords= ["Anglo-Saxon English","American English","British English","Canadian English","Fast British English","Austrian German","American Football","British English","Fast British English","Blue Jeep","Hot Summer","Mild Summer","Hot Brazilian Summer"];

和另一个数组:

var terms = ["english","english","english","english","english","german","football","british english","british english","jeep","summer","summer","summer"];

每个关键字对应于每个关键字,因为每个关键字本身都包含相应的关键字。例如,'Anglo-Saxon English'关键字对应于'english'术语,'American Football'关键字对应于'football'术语等。但是,在关键字数组中有一些重复。在此示例中,重复的关键字是:'英国英语'关键字,对应于'英语'术语以及'英国英语'术语,'快速英国英语'关键词对应于'英语'术语以及'英国英语'术语。可以有任意数量的重复项(为简单起见,我已经添加了2个)。所有关键字在数组中的顺序都相同,因此两个数组的长度相同。

我的问题是如何只留下一个具有更具体对应词的重复词?例如,“英国英语”是比“英语”更具体的术语,因此我想从两个数组中删除“英国英语”(关键字[2])重复关键字及其各自的术语“英语”(术语[2]),并且只留下“英国英语”(keywords [7])关键字,其术语为“英国英语”(条款[7])。

更新:通过下面托博斯提供的解决方案,我想出了工作小提琴:http://jsfiddle.net/ZqEhQ/。然而,这里的“快速英国英语”和“英国英语”仍然被“语言”所吸引,而不是被“汽车”类别所吸引,后者具有更具体的“英国英语”术语而非“英语”术语。 '类别。有什么想法吗?

4 个答案:

答案 0 :(得分:2)

让项目依赖于彼此在不同阵列中的顺序通常是一个坏主意,因为它很难维护。我建议为您的数据使用不同的结构:

var data= [
    { keyword : "Anglo-Saxon English", term : 'english', category : 'Language' },
    { keyword : "American English", term : 'english', category : 'Language'  },
    { keyword : "Fast British English", term : 'english', category : 'Sport' },
    { keyword : "British English", term : 'english', category : 'Language' },
    { keyword : "British English", term : 'british english', category : 'Language' },
    { keyword : "Fast British English", term : 'british english', category : 'Sport' },
    { keyword : "Canadian English", term : 'french', category : 'Sport' }
];

由于您的最终数据包含唯一关键字,因此我会使用另一种数据结构来保存它:

预期产出:

var uniques = {
    "American English": "english"
    "Anglo-Saxon English": "english"
    "British English": "british english"
    "Canadian English": "french"
    "Fast British English": "british english"
}

从输入到预期输出的某种方式:

var uniques = {};
data.forEach(function(item){
    if (isMoreSpecific(item.term, uniques[item.keyword])) {
        uniques [item.keyword] = item.term;
    }
});

function isMoreSpecific(term, reference) {
    return !reference || term.indexOf(reference) !== -1;
}

如果您不同意我的定义或您定义特异性更改的逻辑,您显然可以更改isMoreSpecific函数。你甚至可以内联它,但在这种情况下我更喜欢这个功能。


注意:上面的解决方案很容易适应您最初使用的两个阵列。只需在一个数组上使用for循环迭代即可构建uniques对象,然后从中重建数组。


使用关键字包含类别的解决方案:

var uniques = {};
data.forEach(function(item){
    var serialized = JSON.stringify({key:item.keyword, cat:item.category});
    if (isMoreSpecific(item.term, uniques[serialized])) {
        uniques [serialized] = item.term;
    }
});

var keywordcategory = {};
for (var serialized in uniques) {
    var obj = JSON.parse(serialized);
    keywordcategory[obj.key] = obj.cat;
}

DEMO:http://jsbin.com/ODoDIXi/1/edit

如果您可以假设同一个关键字只在一个类别中,则不需要序列化:

var uniques = {};
data.forEach(function(item){
    if (isMoreSpecific(item.term, uniques[item.keyword].term)) {
        uniques [item.keyword] =  { term : item.term; category : item.category };
    }
});

// you can now remove the unnecessary term information from the uniques map and keep just the category:
for (var key in uniques) {
  uniques[key] = uniques[key].category;
}

答案 1 :(得分:1)

我不确定我是否正确理解,但仍然......

让我们从这个小函数开始:

function removeLessSpecific(ary) {
    return ary.filter(function(x) {
        return !ary.some(function(y) {
            return x != y && y.indexOf(x) >= 0;
        });
    });
}

申请时说

["american football","english","british english","football","german"]

它只返回更具体或“独立”的术语

["american football","british english","german"]

现在让我们将您的数组转换为映射结构:

mapping = {}

keywords.forEach(function(kw, i) {
    mapping[kw] = (mapping[kw] || []);
    mapping[kw].push(terms[i]);
})

映射将如下所示:

{
     "Anglo-Saxon English":["english"],
     "American English":["english"],
     "British English":["english","british english"], etc

最后,迭代映射,删除不太具体的关键字并填充新数组:

newTerms = [], newKw = []

Object.keys(mapping).forEach(function(term) {
    var kwords = mapping[term];
    removeLessSpecific(kwords).forEach(function(kw) {
        newTerms.push(term);
        newKw.push(kw);
    })
})

http://jsfiddle.net/d9Zq8/1/

作为旁注,你的命名对我来说有点混乱。在您的示例中,第一个数组必须是“terms”(=专有名称),第二个数组必须是“keywords”。

答案 2 :(得分:1)

正如蒂博斯所说,你需要重组你的数据。拥有2个阵列并不好。

var data = [
    {keyword: "Anglo-Saxon English", term: 'english'},
    {keyword: "British English", term: 'english'},
    {keyword: "British English", term: 'british english'},
    {keyword: "Fast British English", term: 'british english'},
    {keyword: "Canadian English", term: 'french'}
];

添加唯一数据阵列:

var uniqueData = [];

步骤1-将所有关键字提取到uniqueKeywords数组

var uniqueKeywords = [];

data.forEach(function(item) {

//if keyword doesn't already exist, push it
if (uniqueKeywords.indexOf(item.keyword) === -1)
       uniqueKeywords.push(item.keyword);
});

第2步 - 为每个关键字找到所有相应的数据对象,并仅将最相关的数据对象添加到uniqueData

var extractMostRelevant = function(array){
     var mostRelevant = array[0];

     array.forEach(function(item){
         if(item !== array[0]){
               if(item.term.length > mostRelevant.term.length)
                     mostRelevant = item;
         }
     });

     return mostRelevant;
 };


uniqueKeywords.forEach(function(keyword){
     var itemsWithCurrentKeyword = [];

     data.forEach(function(item){
           if(keyword === item.keyword)
           itemsWithCurrentKeyword.push(item);
     });

     var mostRelevant = extractMostRelevant(itemsWithCurrentKeyword);
     uniqueData.push(mostRelevant);
});

你去了,现在你有2个阵列:datauniqueData

答案 3 :(得分:0)

原始阵列:[1,3,2,1,4,5,6,4,3,5,6,2,3,4,1,4,6,4,10,3,10,“一”, “一个”]

删除了重复:[1,10,2,3,4,5,6,“a”]

Array.prototype.removeDuplicates = function (){
  var temp=new Array();
  this.sort();
  for(i=0;i<this.length;i++)
  if(this[i]==this[i+1]) {continue}
  temp[temp.length]=this[i];
  }
  return temp;
  } 

OR

var duplicatesArray = ['mike','shibu','shibu','alex'];

var uniqueArray = duplicatesArray.filter(function(elem, pos) {
    return duplicatesArray.indexOf(elem) == pos;
  });