2013-08-16 88 views
0

我需要一个函数,它接受一个数组并返回一个包含所有重复项的数组。如果可能,我宁愿使用underscore如何返回数组中的重复字符串数组?

给出的数组:

[ 
    "apple", 
    "apple", 
    "pear", 
    "pear", 
    "kiwi", 
    "peach" 
] 

我需要返回数组

[ 
    "apple", 
    "pear" 
] 

许多我发现会返回一个布尔值,而不是重复的阵列的方法。

例如

var fruits = ["apple","apple"]; 
var uniq_fruits = _.uniq(fruits); 
var duplicates_exist = (fruits.length == uniq_fruits.length); 
+0

你会如何做,如果你没有一个电脑吗? – Pointy

+0

@点传送带和颜色识别? – ThomasReggi

+0

所以如果我在一张纸上写下水果名单,你需要一条传送带来找到重复的东西?是不是有一种更简单的方法来处理水果名单?比如,有没有办法跟踪你所看到的每个名字? – Pointy

回答

5

你可以使用_.countBy来获取单词频率,然后用_.reduce收集频率大于1的值:

function collect_dups(a, n, word) { 
    if(n > 1) 
     a.push(word); 
    return a; 
} 
var dups = _(words).chain() 
        .countBy() 
        .reduce(collect_dups, []) 
        .value(); 

演示:http://jsfiddle.net/ambiguous/gKmfh/1/

+0

这显然是真正的惯用Underscore答案:) – Pointy

0

给你有一个简单的字符串一个级别阵列,我建议第一,然后依次通过它数组排序试图当前项目与下一个比较。 事情是这样的:

var fruit = [ 
    "apple", 
    "apple", 
    "apple", 
    "pear", 
    "pear", 
    "cantalope" 
]; 

var common = function(array){ 
    var mySortedArray = array.sort(); 
    var myResultArray = []; 

    for (var i = 0; i < mySortedArray.length - 1; i++) 
     if ((mySortedArray[i + 1] == mySortedArray[i]) && 
     (mySortedArray[i] != myResultArray[myResultArray.length-1])) 
     myResultArray.push(mySortedArray[i]); 

    return myResultArray; 
}; 

alert(common(fruit)); 
+0

如果数组中有三个或更多相同的东西,这不起作用这里是我的示例https://gist.github.com/reggi/c619ecdab5e9b6746bc8 – ThomasReggi

+0

我修改了它的通用函数以便它开始工作,请参阅上面的 –

3

打开你的名单分成一个地图,然后打开地图到列表中。

var fruits = ["apple", // ... ]; 

function fruitCounter(countMap, fruit) { 
    if (countMap[fruit] == null) 
    countMap[fruit] = 1; 
    else 
    countMap[fruit]++; 
    return countMap; 
} 

function dupFinder(dupList, count, fruit) { 
    if (count > 1) 
    dupList.push(fruit); 
    return dupList; 
} 

var dups = _.reduce(_.reduce(fruits, fruitCounter, {}), dupFinder, []); 

这是排序的不幸的是,没有什么真的很喜欢“过滤器”为对象的属性的,但它也不是太糟糕了“减少”。

编辑 —从别人更好的突出了一个评论,而我指出,内部“减少”可以通过一个简单的“countBy”所取代:

var dups = _.reduce(_.countBy(fruits, function(f) { return f; }), dupFinder, []); 
+1

您可以使用['_.countBy'](http://underscorejs.org/#countBy)而不是'_.reduce'。 –

+0

@ muistooshort啊好的;我几乎不知道下划线:) – Pointy

+2

你也可以用[_.identity](http://underscorejs.org/#identity) – ne8il

1
var common = function(array){ 

    var tally = function(array){ 
     var make_object = {}; 
     _.each(array, function(item){ 
      make_object[item] = (typeof make_object[item] == "undefined") ? 1 : make_object[item] + 1; 
     }); 
     return make_object;   
    }(array); 

    var duplicates = function(obj){ 
     var duplicates = []; 
     _.each(obj, function(value, key){ 
      if(value > 1){ 
       duplicates.push(key); 
      } 
     }); 
     return duplicates; 
    }(tally); 

    return duplicates; 

}; 
1

这个想法非常简单。将项目按其值分组,然后查找哪个组具有多个项目。最后从每个组中选择一个项目。

lst = [ "apple", "apple", "pear", "pear", "kiwi", "peach"]; 
var result = _.chain(lst) 
    .groupBy(function (i) { return i; }) 
    .filter(function (v, k) { return v.length > 1; }) 
    .map(function(v){return v[0]; }) 
    .value(); 

>>["apple", "pear"] 
1

其中ARR是你的输入,你只是检查,看看是否该元素是obj对象上的关键 - 如果它是,它传递到输出数组和RELOOP,否则此键添加到对象:

function findDupes(arr) { 
    var obj = {}, newArr = []; 
    for (var i = 0, l = arr.length; i < l; i++) { 
    if (obj[arr[i]]) { newArr.push(arr[i]); continue; } 
    obj[arr[i]] = true; 
    } 
    return newArr; 
} 

var dupes = findDupes(arr);

+0

为什么它的价值,托马斯,@Pointy谈论什么,他和我展示,是有关Javascript对象的一件伟大的事情 - 他们的钥匙是独一无二的。这意味着你可以分配给他们的东西,并做一个简单的测试,看看他们是否存在。 与先前将整个数组转换为对象(地图)不同,您可以像上面所描述的那样在飞行中完成它,虽然我喜欢下划线以进行大量繁重工作,但这样更容易IMO。 – Andy

+0

如果重复超过两次,这将多次将同一项目推送到结果。 – leaf

0

我从这个函数开始:https://stackoverflow.com/a/840849/1636522

function getDuplicates(arr) { 
    var i, 
     len = arr.length, 
     out = [], 
     obj = {}; 
    for (i = 0; i < len; i++) { 
     switch (obj[arr[i]]) { 
      case undefined: obj[arr[i]] = 1; break; 
      case 1: obj[arr[i]] = 2; out.push(arr[i]); break; 
     } 
    } 
    return out; 
}